Compare commits

..

20 Commits

Author SHA1 Message Date
9a87a52ed6 chore(release): 1.2.7 2025-05-01 16:12:13 +02:00
93e30efd8a chore: update openapi.json 2025-05-01 16:12:05 +02:00
a595166b9d fix: Correct quote style in update:commit script in package.json 2025-05-01 16:11:41 +02:00
d6a11cf418 feat: Enhance update:auto script to include commit step for openapi.json 2025-05-01 16:10:33 +02:00
645cc59535 chore(release): 1.2.6 2025-05-01 16:08:16 +02:00
00ce1c6b3a fix: Update release script to include npm publish for proper deployment 2025-05-01 16:06:58 +02:00
4fa6e8a1db feat: Update release script to only version for streamlined releases 2025-04-28 21:37:06 +02:00
87e05ff637 chore: Remove unused hooks from release-it configuration 2025-04-28 20:28:45 +02:00
03a778c24f refactor: Rename update script to update:auto for clarity 2025-04-28 20:27:38 +02:00
ef2bc38a63 docs: Update README with detailed setup and build instructions 2025-04-28 20:26:32 +02:00
26d518fb8e feat: Added scripts to auto-update to latest version 2025-04-28 20:24:22 +02:00
087371b3ce feat: Added release script 2025-04-28 20:20:49 +02:00
7238275835 bump version to 1.2.5 in package.json 2025-04-28 19:51:15 +02:00
962d1f40b4 chore: Fresh openapi spec 2025-04-28 19:50:55 +02:00
f2e54490f2 bump version to 1.2.4 in package.json 2025-04-17 21:01:57 +02:00
ea3d42427b chore(release): 1.2.3 2025-04-09 11:45:59 +02:00
fb04bb8dc2 chore: 1.2.2 2025-04-08 21:10:08 +02:00
cdddf5c2b4 chore: Fresh openapi 2025-04-08 21:09:51 +02:00
a4747a23e7 chore: 1.2.1 2025-04-08 20:09:18 +02:00
9b36d6e6dc chore: Fresh build 2025-04-08 20:09:05 +02:00
38 changed files with 2025 additions and 21 deletions

View File

@@ -5,7 +5,25 @@ The official library for the LfK [backend server](https://git.odit.services/lfk/
Automagicly™ generated by [openapi-typescript-codegen](https://www.npmjs.com/package/openapi-typescript-codegen) Automagicly™ generated by [openapi-typescript-codegen](https://www.npmjs.com/package/openapi-typescript-codegen)
## 🛠 Building ## 🛠 Building
Get's automagicly™ build by drone for every new backend release.
### Setup ⬇️
```bash
git clone https://git.odit.services/lfk/lfk-client-js.git
cd lfk-client-js
pnpm i
```
### Build 🔨
```bash
pnpm update:openapi # Update the openapi.json file
pnpm build # Build the project
pnpm release # Bump and release to npm
# Or just do it all in one command
pnpm update:auto
```
## Use ## Use

View File

@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAPI = void 0; exports.OpenAPI = void 0;
exports.OpenAPI = { exports.OpenAPI = {
BASE: '', BASE: '',
VERSION: '1.3.4', VERSION: '1.4.3',
WITH_CREDENTIALS: false, WITH_CREDENTIALS: false,
TOKEN: undefined, TOKEN: undefined,
USERNAME: undefined, USERNAME: undefined,

3
dist/index.d.ts vendored
View File

@@ -7,6 +7,7 @@ export type { AddressFirstLineEmptyError } from './models/AddressFirstLineEmptyE
export type { AddressPostalCodeEmptyError } from './models/AddressPostalCodeEmptyError'; export type { AddressPostalCodeEmptyError } from './models/AddressPostalCodeEmptyError';
export type { AddressPostalCodeInvalidError } from './models/AddressPostalCodeInvalidError'; export type { AddressPostalCodeInvalidError } from './models/AddressPostalCodeInvalidError';
export type { ConfigFlag } from './models/ConfigFlag'; export type { ConfigFlag } from './models/ConfigFlag';
export type { CreateAnonymousDonation } from './models/CreateAnonymousDonation';
export type { CreateAuth } from './models/CreateAuth'; export type { CreateAuth } from './models/CreateAuth';
export type { CreateDistanceDonation } from './models/CreateDistanceDonation'; export type { CreateDistanceDonation } from './models/CreateDistanceDonation';
export type { CreateDonation } from './models/CreateDonation'; export type { CreateDonation } from './models/CreateDonation';
@@ -70,6 +71,7 @@ export type { RefreshAuth } from './models/RefreshAuth';
export type { RefreshTokenCountInvalidError } from './models/RefreshTokenCountInvalidError'; export type { RefreshTokenCountInvalidError } from './models/RefreshTokenCountInvalidError';
export type { ResetAlreadyRequestedError } from './models/ResetAlreadyRequestedError'; export type { ResetAlreadyRequestedError } from './models/ResetAlreadyRequestedError';
export type { ResetPassword } from './models/ResetPassword'; export type { ResetPassword } from './models/ResetPassword';
export type { ResponseAnonymousDonation } from './models/ResponseAnonymousDonation';
export type { ResponseAuth } from './models/ResponseAuth'; export type { ResponseAuth } from './models/ResponseAuth';
export type { ResponseDistanceDonation } from './models/ResponseDistanceDonation'; export type { ResponseDistanceDonation } from './models/ResponseDistanceDonation';
export type { ResponseDonation } from './models/ResponseDonation'; export type { ResponseDonation } from './models/ResponseDonation';
@@ -152,6 +154,7 @@ export type { UpdateGroupContact } from './models/UpdateGroupContact';
export type { UpdatePermission } from './models/UpdatePermission'; export type { UpdatePermission } from './models/UpdatePermission';
export type { UpdateRunner } from './models/UpdateRunner'; export type { UpdateRunner } from './models/UpdateRunner';
export type { UpdateRunnerCard } from './models/UpdateRunnerCard'; export type { UpdateRunnerCard } from './models/UpdateRunnerCard';
export type { UpdateRunnerCardByCode } from './models/UpdateRunnerCardByCode';
export type { UpdateRunnerOrganization } from './models/UpdateRunnerOrganization'; export type { UpdateRunnerOrganization } from './models/UpdateRunnerOrganization';
export type { UpdateRunnerTeam } from './models/UpdateRunnerTeam'; export type { UpdateRunnerTeam } from './models/UpdateRunnerTeam';
export type { UpdateScan } from './models/UpdateScan'; export type { UpdateScan } from './models/UpdateScan';

View File

@@ -0,0 +1,5 @@
export type CreateAnonymousDonation = {
amount: number;
donor?: number;
paidAmount?: number;
};

View File

@@ -0,0 +1,5 @@
"use strict";
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,6 +1,6 @@
export type CreateDistanceDonation = { export type CreateDistanceDonation = {
donor?: number;
paidAmount?: number;
runner: number; runner: number;
amountPerDistance: number; amountPerDistance: number;
donor: number;
paidAmount?: number;
}; };

View File

@@ -1,4 +1,4 @@
export type CreateDonation = { export type CreateDonation = {
donor: number; donor?: number;
paidAmount?: number; paidAmount?: number;
}; };

View File

@@ -6,4 +6,5 @@ export type CreateDonor = {
phone?: string; phone?: string;
email?: string; email?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -1,5 +1,5 @@
export type CreateFixedDonation = { export type CreateFixedDonation = {
amount: number; donor?: number;
donor: number;
paidAmount?: number; paidAmount?: number;
amount: number;
}; };

View File

@@ -5,4 +5,5 @@ export type CreateParticipant = {
phone?: string; phone?: string;
email?: string; email?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -6,4 +6,5 @@ export type CreateRunner = {
phone?: string; phone?: string;
email?: string; email?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -5,4 +5,5 @@ export type CreateSelfServiceCitizenRunner = {
lastname: string; lastname: string;
phone?: string; phone?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -6,4 +6,5 @@ export type CreateSelfServiceRunner = {
phone?: string; phone?: string;
email?: string; email?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -2,6 +2,5 @@ export type DistanceDonation = {
runner: string; runner: string;
amountPerDistance: number; amountPerDistance: number;
id: number; id: number;
donor: string;
paidAmount: number; paidAmount: number;
}; };

View File

@@ -1,5 +1,4 @@
export type Donation = { export type Donation = {
id: number; id: number;
donor: string;
paidAmount: number; paidAmount: number;
}; };

View File

@@ -2,6 +2,5 @@ export type FixedDonation = {
_amount: number; _amount: number;
amount: number; amount: number;
id: number; id: number;
donor: string;
paidAmount: number; paidAmount: number;
}; };

View File

@@ -0,0 +1,5 @@
export type ResponseAnonymousDonation = {
id: number;
amount: number;
paidAmount: number;
};

View File

@@ -0,0 +1,5 @@
"use strict";
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,6 +1,8 @@
export type ResponseRunner = { export type ResponseRunner = {
distance: number; distance: number;
donationAmount: number;
group: any; group: any;
selfserviceLink?: string;
id: number; id: number;
firstname: string; firstname: string;
middlename: string; middlename: string;

View File

@@ -1,5 +1,6 @@
export type ResponseStats = { export type ResponseStats = {
runnersViaSelfservice: number; runnersViaSelfservice: number;
runnersViaKiosk: number;
total_runners: number; total_runners: number;
total_teams: number; total_teams: number;
total_orgs: number; total_orgs: number;

View File

@@ -7,4 +7,5 @@ export type UpdateDonor = {
phone?: string; phone?: string;
email?: string; email?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -7,4 +7,5 @@ export type UpdateRunner = {
phone?: string; phone?: string;
email?: string; email?: string;
address?: any; address?: any;
created_via?: string;
}; };

View File

@@ -0,0 +1,5 @@
export type UpdateRunnerCardByCode = {
code: string;
runner?: number;
enabled: boolean;
};

5
dist/models/UpdateRunnerCardByCode.js vendored Normal file
View File

@@ -0,0 +1,5 @@
"use strict";
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -1,5 +1,7 @@
import type { CreateAnonymousDonation } from '../models/CreateAnonymousDonation';
import type { CreateDistanceDonation } from '../models/CreateDistanceDonation'; import type { CreateDistanceDonation } from '../models/CreateDistanceDonation';
import type { CreateFixedDonation } from '../models/CreateFixedDonation'; import type { CreateFixedDonation } from '../models/CreateFixedDonation';
import type { ResponseAnonymousDonation } from '../models/ResponseAnonymousDonation';
import type { ResponseDistanceDonation } from '../models/ResponseDistanceDonation'; import type { ResponseDistanceDonation } from '../models/ResponseDistanceDonation';
import type { ResponseDonation } from '../models/ResponseDonation'; import type { ResponseDonation } from '../models/ResponseDonation';
import type { ResponseEmpty } from '../models/ResponseEmpty'; import type { ResponseEmpty } from '../models/ResponseEmpty';
@@ -14,7 +16,7 @@ export declare class DonationService {
* @result any * @result any
* @throws ApiError * @throws ApiError
*/ */
static donationControllerGetAll(page?: number, pageSize?: number): Promise<(Array<ResponseDonation> | Array<ResponseDistanceDonation>)>; static donationControllerGetAll(page?: number, pageSize?: number): Promise<(Array<ResponseDonation> | Array<ResponseDistanceDonation> | Array<ResponseAnonymousDonation>)>;
/** /**
* Get one * Get one
* Lists all information about the donation whose id got provided. This includes the donation's runner's distance ran (if distance donation). * Lists all information about the donation whose id got provided. This includes the donation's runner's distance ran (if distance donation).
@@ -22,7 +24,7 @@ export declare class DonationService {
* @result any * @result any
* @throws ApiError * @throws ApiError
*/ */
static donationControllerGetOne(id: number): Promise<(ResponseDonation | ResponseDistanceDonation)>; static donationControllerGetOne(id: number): Promise<(ResponseDonation | ResponseDistanceDonation | ResponseAnonymousDonation)>;
/** /**
* Remove * Remove
* Delete the donation whose id you provided. <br> If no donation with this id exists it will just return 204(no content). * Delete the donation whose id you provided. <br> If no donation with this id exists it will just return 204(no content).
@@ -41,6 +43,14 @@ export declare class DonationService {
* @throws ApiError * @throws ApiError
*/ */
static donationControllerPostFixed(requestBody?: CreateFixedDonation): Promise<ResponseDonation>; static donationControllerPostFixed(requestBody?: CreateFixedDonation): Promise<ResponseDonation>;
/**
* Post anonymous
* Create a anonymous donation
* @param requestBody CreateAnonymousDonation
* @result ResponseDonation
* @throws ApiError
*/
static donationControllerPostAnonymous(requestBody?: CreateAnonymousDonation): Promise<ResponseDonation>;
/** /**
* Post distance * Post distance
* Create a distance donation (not fixed donation - use /donations/fixed instead). <br> Please rmemember to provide the donation's donors's and runners ids and amount per distance (kilometer). * Create a distance donation (not fixed donation - use /donations/fixed instead). <br> Please rmemember to provide the donation's donors's and runners ids and amount per distance (kilometer).

View File

@@ -70,6 +70,21 @@ class DonationService {
}); });
return result.body; return result.body;
} }
/**
* Post anonymous
* Create a anonymous donation
* @param requestBody CreateAnonymousDonation
* @result ResponseDonation
* @throws ApiError
*/
static async donationControllerPostAnonymous(requestBody) {
const result = await (0, request_1.request)({
method: 'POST',
path: `/api/donations/anonymous`,
body: requestBody,
});
return result.body;
}
/** /**
* Post distance * Post distance
* Create a distance donation (not fixed donation - use /donations/fixed instead). <br> Please rmemember to provide the donation's donors's and runners ids and amount per distance (kilometer). * Create a distance donation (not fixed donation - use /donations/fixed instead). <br> Please rmemember to provide the donation's donors's and runners ids and amount per distance (kilometer).

View File

@@ -2,6 +2,7 @@ import type { CreateRunnerCard } from '../models/CreateRunnerCard';
import type { ResponseEmpty } from '../models/ResponseEmpty'; import type { ResponseEmpty } from '../models/ResponseEmpty';
import type { ResponseRunnerCard } from '../models/ResponseRunnerCard'; import type { ResponseRunnerCard } from '../models/ResponseRunnerCard';
import type { UpdateRunnerCard } from '../models/UpdateRunnerCard'; import type { UpdateRunnerCard } from '../models/UpdateRunnerCard';
import type { UpdateRunnerCardByCode } from '../models/UpdateRunnerCardByCode';
export declare class RunnerCardService { export declare class RunnerCardService {
/** /**
* Get all * Get all
@@ -56,4 +57,13 @@ export declare class RunnerCardService {
* @throws ApiError * @throws ApiError
*/ */
static runnerCardControllerPostBlancoBulk(count?: number, returnCards?: boolean): Promise<ResponseEmpty>; static runnerCardControllerPostBlancoBulk(count?: number, returnCards?: boolean): Promise<ResponseEmpty>;
/**
* Put by code
* Update the card whose code you provided.
* @param code
* @param requestBody UpdateRunnerCardByCode
* @result ResponseRunnerCard
* @throws ApiError
*/
static runnerCardControllerPutByCode(code: string, requestBody?: UpdateRunnerCardByCode): Promise<ResponseRunnerCard>;
} }

View File

@@ -105,5 +105,21 @@ class RunnerCardService {
}); });
return result.body; return result.body;
} }
/**
* Put by code
* Update the card whose code you provided.
* @param code
* @param requestBody UpdateRunnerCardByCode
* @result ResponseRunnerCard
* @throws ApiError
*/
static async runnerCardControllerPutByCode(code, requestBody) {
const result = await (0, request_1.request)({
method: 'PUT',
path: `/api/cards/${code}`,
body: requestBody,
});
return result.body;
}
} }
exports.RunnerCardService = RunnerCardService; exports.RunnerCardService = RunnerCardService;

View File

@@ -53,8 +53,9 @@ export declare class RunnerOrganizationService {
* Lists all runners from this org and it's teams (if you don't provide the ?onlyDirect=true param). <br> This includes the runner's group and distance ran. * Lists all runners from this org and it's teams (if you don't provide the ?onlyDirect=true param). <br> This includes the runner's group and distance ran.
* @param id * @param id
* @param onlyDirect * @param onlyDirect
* @param selfserviceLinks
* @result ResponseRunner * @result ResponseRunner
* @throws ApiError * @throws ApiError
*/ */
static runnerOrganizationControllerGetRunners(id: number, onlyDirect?: boolean): Promise<Array<ResponseRunner>>; static runnerOrganizationControllerGetRunners(id: number, onlyDirect?: boolean, selfserviceLinks?: boolean): Promise<Array<ResponseRunner>>;
} }

View File

@@ -91,15 +91,17 @@ class RunnerOrganizationService {
* Lists all runners from this org and it's teams (if you don't provide the ?onlyDirect=true param). <br> This includes the runner's group and distance ran. * Lists all runners from this org and it's teams (if you don't provide the ?onlyDirect=true param). <br> This includes the runner's group and distance ran.
* @param id * @param id
* @param onlyDirect * @param onlyDirect
* @param selfserviceLinks
* @result ResponseRunner * @result ResponseRunner
* @throws ApiError * @throws ApiError
*/ */
static async runnerOrganizationControllerGetRunners(id, onlyDirect) { static async runnerOrganizationControllerGetRunners(id, onlyDirect, selfserviceLinks) {
const result = await (0, request_1.request)({ const result = await (0, request_1.request)({
method: 'GET', method: 'GET',
path: `/api/organizations/${id}/runners`, path: `/api/organizations/${id}/runners`,
query: { query: {
'onlyDirect': onlyDirect, 'onlyDirect': onlyDirect,
'selfservice_links': selfserviceLinks,
}, },
}); });
return result.body; return result.body;

View File

@@ -12,10 +12,12 @@ export declare class RunnerService {
* Lists all runners from all teams/orgs. <br> This includes the runner's group and distance ran. * Lists all runners from all teams/orgs. <br> This includes the runner's group and distance ran.
* @param page * @param page
* @param pageSize * @param pageSize
* @param createdVia
* @param selfserviceLinks
* @result ResponseRunner * @result ResponseRunner
* @throws ApiError * @throws ApiError
*/ */
static runnerControllerGetAll(page?: number, pageSize?: number): Promise<Array<ResponseRunner>>; static runnerControllerGetAll(page?: number, pageSize?: number, createdVia?: string, selfserviceLinks?: boolean): Promise<Array<ResponseRunner>>;
/** /**
* Post * Post
* Create a new runner. <br> Please remeber to provide the runner's group's id. * Create a new runner. <br> Please remeber to provide the runner's group's id.

View File

@@ -8,16 +8,20 @@ class RunnerService {
* Lists all runners from all teams/orgs. <br> This includes the runner's group and distance ran. * Lists all runners from all teams/orgs. <br> This includes the runner's group and distance ran.
* @param page * @param page
* @param pageSize * @param pageSize
* @param createdVia
* @param selfserviceLinks
* @result ResponseRunner * @result ResponseRunner
* @throws ApiError * @throws ApiError
*/ */
static async runnerControllerGetAll(page, pageSize) { static async runnerControllerGetAll(page, pageSize, createdVia, selfserviceLinks) {
const result = await (0, request_1.request)({ const result = await (0, request_1.request)({
method: 'GET', method: 'GET',
path: `/api/runners`, path: `/api/runners`,
query: { query: {
'page': page, 'page': page,
'page_size': pageSize, 'page_size': pageSize,
'created_via': createdVia,
'selfservice_links': selfserviceLinks,
}, },
}); });
return result.body; return result.body;

View File

@@ -52,8 +52,9 @@ export declare class RunnerTeamService {
* Get runners * Get runners
* Lists all runners from this team. <br> This includes the runner's group and distance ran. * Lists all runners from this team. <br> This includes the runner's group and distance ran.
* @param id * @param id
* @param selfserviceLinks
* @result ResponseRunner * @result ResponseRunner
* @throws ApiError * @throws ApiError
*/ */
static runnerTeamControllerGetRunners(id: number): Promise<Array<ResponseRunner>>; static runnerTeamControllerGetRunners(id: number, selfserviceLinks?: boolean): Promise<Array<ResponseRunner>>;
} }

View File

@@ -90,13 +90,17 @@ class RunnerTeamService {
* Get runners * Get runners
* Lists all runners from this team. <br> This includes the runner's group and distance ran. * Lists all runners from this team. <br> This includes the runner's group and distance ran.
* @param id * @param id
* @param selfserviceLinks
* @result ResponseRunner * @result ResponseRunner
* @throws ApiError * @throws ApiError
*/ */
static async runnerTeamControllerGetRunners(id) { static async runnerTeamControllerGetRunners(id, selfserviceLinks) {
const result = await (0, request_1.request)({ const result = await (0, request_1.request)({
method: 'GET', method: 'GET',
path: `/api/teams/${id}/runners`, path: `/api/teams/${id}/runners`,
query: {
'selfservice_links': selfserviceLinks,
},
}); });
return result.body; return result.body;
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
{ {
"name": "@odit/lfk-client-js", "name": "@odit/lfk-client-js",
"description": "A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.", "description": "A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.",
"version": "1.2.0", "version": "1.2.7",
"license": "CC-BY-NC-SA-4.0", "license": "CC-BY-NC-SA-4.0",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -25,7 +25,11 @@
"build:prepare": "rimraf ./lib ./dist", "build:prepare": "rimraf ./lib ./dist",
"build:lib": "openapi --input ./openapi.json --output ./lib --client fetch", "build:lib": "openapi --input ./openapi.json --output ./lib --client fetch",
"build:compile": "tsc", "build:compile": "tsc",
"build:cleanup": "rimraf ./lib" "build:cleanup": "rimraf ./lib",
"update:openapi": "rimraf ./openapi.json && node ./scripts/getliveopenapi.js",
"update:auto": "npm run update:openapi && npm run build && npm run update:commit && npm run release",
"update:commit": "git add . && git commit -m \"chore: update openapi.json\"",
"release": "release-it --only-version && npm publish"
}, },
"bugs": { "bugs": {
"url": "https://git.odit.services/lfk/lfk-client-js/issues" "url": "https://git.odit.services/lfk/lfk-client-js/issues"
@@ -33,7 +37,22 @@
"homepage": "https://git.odit.services/lfk/lfk-client-js/", "homepage": "https://git.odit.services/lfk/lfk-client-js/",
"devDependencies": { "devDependencies": {
"openapi-typescript-codegen": "0.7.0", "openapi-typescript-codegen": "0.7.0",
"release-it": "17.10.0",
"rimraf": "6.0.1", "rimraf": "6.0.1",
"typescript": "4.9.5" "typescript": "4.9.5"
},
"release-it": {
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "chore(release): ${version}",
"push": true,
"tag": true,
"tagName": "${version}",
"tagAnnotation": "${version}"
},
"npm": {
"publish": false
}
} }
} }

1835
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

27
scripts/getliveopenapi.js Normal file
View File

@@ -0,0 +1,27 @@
const https = require('https');
const fs = require('fs');
const url = 'https://run.lauf-fuer-kaya.de/api/docs/openapi.json';
const output = 'openapi.json';
https.get(url, (res) => {
if (res.statusCode !== 200) {
console.error(`Request Failed. Status Code: ${res.statusCode}`);
res.resume();
return;
}
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
fs.writeFile(output, data, (err) => {
if (err) {
console.error('Error writing file:', err);
} else {
console.log(`Saved latest OpenAPI JSON to ${output}`);
}
});
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});