Skip to content

Commit 81b7aaf

Browse files
committed
feat: create cli
Signed-off-by: aabidsofi19 <mailtoaabid01@gmail.com>
1 parent beb3533 commit 81b7aaf

File tree

8 files changed

+1791
-0
lines changed

8 files changed

+1791
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@
1616

1717
# IDEs
1818
.vscode/*
19+
20+
# Node.js
21+
node_modules/
22+

package-lock.json

Lines changed: 1603 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@layer5/rtk-query-codegen",
3+
"version": "0.0.1",
4+
"description": "Codegen to create rtk-query api from openapi schema",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"bin": {
10+
"rtk-query-codegen": "./app.js"
11+
},
12+
"author": "",
13+
"dependencies": {
14+
"@reduxjs/toolkit": "^1.9.6",
15+
"@rtk-query/codegen-openapi": "^1.0.0",
16+
"commander": "^11.0.0",
17+
"prettier-plugin-organize-imports": "^3.2.3",
18+
"ts-node": "^10.9.1"
19+
}
20+
}

src/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# OpenAPI API Client Generation and Compilation
2+
3+
Generate an API client from an OpenAPI schema in YAML format and create a rtk-query api client. The provided Bash script streamlines this process and ensures a smooth workflow.
4+
5+
## Dependencies
6+
7+
Before proceeding, ensure you have the following dependencies installed:
8+
9+
1. **Node.js and npm:** Ensure you have Node.js and npm installed on your system. You can download them from [nodejs.org](https://nodejs.org/).
10+
11+
2. **redocly CLI (required):** If you prefer to use `swagger-cli` for schema conversion, you can install it globally using npm:
12+
13+
```bash
14+
npm i -g @redocly/cli@latest
15+
```
16+
17+
3 **TypeScript:**
18+
19+
```bash
20+
npm i -g typescript
21+
```
22+
23+
## Usage
24+
25+
1. **Execute the Cli:**
26+
27+
- Run the script using the following command:
28+
29+
```bash
30+
rtk-query-codegen -i /path/to/schema.yml -o /path/to/generated-api.js
31+
```
32+
33+
The script will execute the following steps:
34+
35+
a. Convert the YAML schema (at `../../../models/openapi-schema/schema.yml`) to JSON schema at using `redocly` and save it as `openapi.json`.
36+
37+
b. Generate the API client code using `@rtk-query/codegen-openapi` based on the JSON schema.
38+
39+
c. Compile the TypeScript code to JavaScript using the TypeScript Compiler (`tsc`).
40+
41+
d. Move the generated `api.js` to the output and remove the `dist` folder.
42+
43+
2. **Verification:** After executing the script, check your project directory for the compiled `api.js` file. You can use this file as your API client in your project.
44+
45+
## The Api.js file
46+
47+
The api.js file contains the generated api endpoints , it injects them into the base rtk client . And then exports all the hooks to use them .
48+
If we need to override an api endpoint we can injectEnpoints in a separate file .
49+
50+
## Troubleshooting
51+
52+
- If any of the steps fail, the script will exit with a non-zero status code, indicating a failure. Review the error messages to diagnose and resolve any issues.
53+
54+
- Ensure that the Bash script is executable by running `chmod +x generate-api.sh`.
55+
56+
## Important Notes
57+
58+
- Make sure the OpenAPI schema (`schema.yml`) is updated with latest changes and doesnt contain any breaking changes .
59+
60+
- Always validate and test the generated API client to ensure it functions as expected.

src/app.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const { program } = require('commander');
2+
const { exec } = require('child_process');
3+
const { renameSync, rmdirSync, unlinkSync } = require('fs');
4+
const { dirname, basename, join } = require('path');
5+
6+
program
7+
.option('-i, --input <input>', 'Input YAML schema file path')
8+
.option('-o, --output <output>', 'Output path including the filename (e.g., /output/api.js)')
9+
.parse(process.argv);
10+
11+
// Function to run a command and handle success or failure
12+
function runCommand(command, successMessage, failureMessage) {
13+
return new Promise((resolve, reject) => {
14+
exec(command, (error, stdout, stderr) => {
15+
if (error) {
16+
console.error(failureMessage);
17+
console.error(stderr);
18+
reject(error);
19+
} else {
20+
console.log(successMessage);
21+
resolve();
22+
}
23+
});
24+
});
25+
}
26+
27+
async function generateAPI(inputFilePath, outputFilePath) {
28+
try {
29+
// Convert YAML schema to JSON schema
30+
const yamlToJSONCommand = `redocly bundle ${inputFilePath} -o ./openapi.json --ext json`;
31+
await runCommand(yamlToJSONCommand, 'JSON bundle generation successful', 'JSON bundle generation failed');
32+
33+
// Run OpenAPI generator
34+
const openApiGeneratorCommand = 'npx @rtk-query/codegen-openapi openapi-config.ts';
35+
await runCommand(openApiGeneratorCommand, 'OpenAPI generation successful', 'OpenAPI generation failed');
36+
37+
// Run TypeScript compilation
38+
const tscCommand = 'tsc --build tsconfig.json';
39+
await runCommand(tscCommand, 'TypeScript compilation successful', 'TypeScript compilation failed');
40+
41+
// Move api.js from the generated folder to the output path
42+
console.log('Removing Build Artifacts');
43+
const outputPath = dirname(outputFilePath);
44+
const outputFilename = basename(outputFilePath);
45+
renameSync('./dist/api.js', join(outputPath, outputFilename));
46+
rmdirSync('./dist', { recursive: true });
47+
unlinkSync('./openapi.json');
48+
unlinkSync('./api.ts');
49+
50+
console.log('API generation successful');
51+
process.exit(0);
52+
} catch (error) {
53+
console.error('API generation failed');
54+
process.exit(1);
55+
}
56+
}
57+
58+
const { input, output } = program.opts();
59+
60+
if (!input || !output) {
61+
console.error('Please provide both input and output options.');
62+
process.exit(1);
63+
}
64+
65+
generateAPI(input, output);

src/empty-api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
2+
3+
// initialize an empty api service that we'll inject endpoints into later as needed
4+
// the name should be same as the of the api in ../index.js
5+
export const api = createApi({
6+
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
7+
endpoints: () => ({})
8+
});

src/openapi-config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { ConfigFile } from '@rtk-query/codegen-openapi';
2+
const config: ConfigFile = {
3+
schemaFile: './openapi.json',
4+
apiFile: './empty-api.ts',
5+
apiImport: 'api',
6+
exportName: 'api',
7+
hooks: true,
8+
tag: true,
9+
outputFile: './api.ts'
10+
};
11+
12+
export default config;

src/tsconfig.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ESNext",
4+
"esModuleInterop": true,
5+
"forceConsistentCasingInFileNames": false,
6+
"strict": false,
7+
"noImplicitAny": false, // Disable implicit 'any' types
8+
"skipLibCheck": true,
9+
"module": "ESNext",
10+
"declaration": false,
11+
"sourceMap": false,
12+
"moduleResolution": "node",
13+
"allowSyntheticDefaultImports": true,
14+
"emitDeclarationOnly": false,
15+
"allowJs": true,
16+
"outDir": "./dist"
17+
},
18+
"files": ["api.ts"]
19+
}

0 commit comments

Comments
 (0)