react-query-lightbase-codegen 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,7 +35,8 @@ function generateAxiosMethod(operation, spec) {
35
35
  const desc = "description" in responseObj ? responseObj.description : "";
36
36
  const contentType = responseObj.content?.["application/ld+json"]?.schema ??
37
37
  responseObj.content?.["application/json"]?.schema ??
38
- responseObj.content?.["application/octet-stream"]?.schema;
38
+ responseObj.content?.["application/octet-stream"]?.schema ??
39
+ responseObj.content?.["application/json;charset=UTF-8"]?.schema;
39
40
  const typeName = (0, utils_1.pascalCase)(`${operationId}Response${code}`);
40
41
  if (contentType) {
41
42
  if (desc) {
@@ -57,7 +58,8 @@ function generateAxiosMethod(operation, spec) {
57
58
  const content = requestBody && "content" in requestBody
58
59
  ? (requestBody.content?.["application/ld+json"]?.schema ??
59
60
  requestBody.content?.["application/json"]?.schema ??
60
- requestBody.content?.["application/octet-stream"]?.schema)
61
+ requestBody.content?.["application/octet-stream"]?.schema ??
62
+ requestBody.content?.["application/json;charset=UTF-8"]?.schema)
61
63
  : undefined;
62
64
  const requestBodySchema = content ? resolveSchema(content, spec) : undefined;
63
65
  // Add request body type if it exists
@@ -69,7 +71,7 @@ function generateAxiosMethod(operation, spec) {
69
71
  : "unknown";
70
72
  const urlWithParams = urlParams.length > 0 ? `\`${path.replace(/{(\w+)}/g, "${data.$1}")}\`` : `"${path}"`;
71
73
  const methodBody = [
72
- `${hasData ? "const { axiosConfig, ...data } = props || {};" : "const { axiosConfig } = props || {};"}`,
74
+ `${hasData ? "const { axiosConfig = {}, ...data } = props || {};" : "const { axiosConfig } = props || {};"}`,
73
75
  "const apiClient = getApiClient();",
74
76
  `const url = ${urlWithParams};`,
75
77
  queryParams.length > 0
@@ -85,28 +87,33 @@ function generateAxiosMethod(operation, spec) {
85
87
  };`
86
88
  : "",
87
89
  formDataSchema?.properties
88
- ? `const formData = new FormData();
90
+ ? `const bodyData = new FormData();
89
91
  ${Object.entries(formDataSchema.properties)
90
92
  .map(([key, prop]) => {
91
93
  const schemaProperty = prop;
92
94
  const isBinary = schemaProperty.format === "binary";
93
95
  return formDataSchema?.required?.includes(key)
94
- ? `formData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});`
96
+ ? `bodyData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});`
95
97
  : `if (${queryParams.length > 0 ? "bodyData" : "data"}.${key} != null) {
96
- formData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});
98
+ bodyData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});
97
99
  }`;
98
100
  })
99
101
  .join("\n ")}`
100
102
  : "",
101
- `const res = await apiClient.${method}<${responseType}>(url, {
102
- ${queryParams.length > 0 ? "params: queryData," : ""}
103
- ${requestBody ? `data: ${isFormData ? "formData" : "bodyData"},` : ""}
104
- ${isFormData ? `config: { headers: { 'Content-Type': 'multipart/form-data', ...axiosConfig?.headers }, ...axiosConfig },` : "...axiosConfig"}
105
- });
106
- return res.data;`,
103
+ queryParams.length > 0 ? "axiosConfig.params = queryData;" : "",
104
+ isFormData
105
+ ? "axiosConfig.headers = { ...axiosConfig.headers, 'Content-Type': 'multipart/form-data' };"
106
+ : "",
107
+ requestBody
108
+ ? `const res = await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties ? "bodyData" : "data"}, axiosConfig);`
109
+ : `const res = await apiClient.${method}<${responseType}>(url, axiosConfig);`,
110
+ "return res.data;",
107
111
  ]
108
112
  .filter(Boolean)
109
113
  .join("\n ");
114
+ // ${queryParams.length > 0 ? "params: queryData," : ""}
115
+ // ${requestBody ? `data: ${isFormData ? "formData" : "bodyData"},` : ""}
116
+ // ${isFormData ? `config: { headers: { 'Content-Type': 'multipart/form-data', ...axiosConfig?.headers }, ...axiosConfig },` : "...axiosConfig"}
110
117
  const requestParms = hasData
111
118
  ? `props: T.${(0, utils_1.pascalCase)(operationId)}Params & { axiosConfig?: AxiosRequestConfig; }`
112
119
  : "props?: { axiosConfig?: AxiosRequestConfig }";
@@ -45,7 +45,8 @@ function generateTypeDefinitions(spec) {
45
45
  const jsonContent = content["application/ld+json"] ??
46
46
  content["application/json"] ??
47
47
  content["multipart/form-data"] ??
48
- content["application/octet-stream"];
48
+ content["application/octet-stream"] ??
49
+ content["application/json;charset=UTF-8"];
49
50
  if (jsonContent?.schema) {
50
51
  const typeName = `${operationId}Request`;
51
52
  output += generateTypeDefinition(typeName, jsonContent.schema);
@@ -57,7 +58,8 @@ function generateTypeDefinitions(spec) {
57
58
  const responseObj = response;
58
59
  const content = responseObj.content?.["application/ld+json"] ??
59
60
  responseObj.content?.["application/json"] ??
60
- responseObj.content?.["application/octet-stream"];
61
+ responseObj.content?.["application/octet-stream"] ??
62
+ responseObj.content?.["application/json;charset=UTF-8"];
61
63
  if (content?.schema) {
62
64
  const typeName = `${operationId}Response${code}`;
63
65
  output += generateTypeDefinition(typeName, content.schema);
package/dist/index.js CHANGED
@@ -40,6 +40,7 @@ exports.codegenerate = codegenerate;
40
40
  const promises_1 = require("node:fs/promises");
41
41
  const node_path_1 = require("node:path");
42
42
  const axios_1 = __importDefault(require("axios"));
43
+ const swagger2openapi_1 = require("swagger2openapi");
43
44
  const yaml = __importStar(require("yaml"));
44
45
  const clientGenerator_1 = require("./generator/clientGenerator");
45
46
  const instanceGenerator_1 = require("./generator/instanceGenerator");
@@ -51,16 +52,27 @@ const utils_1 = require("./utils");
51
52
  */
52
53
  async function loadOpenAPISpec(specSource) {
53
54
  try {
55
+ let spec;
54
56
  if (specSource.startsWith("http")) {
55
57
  const response = await axios_1.default.get(specSource);
56
- // Check if response is YAML by looking for common YAML indicators
57
- const isYaml = typeof response.data === "string" &&
58
- (response.data.trim().startsWith("openapi:") || response.data.trim().startsWith("swagger:"));
59
- return isYaml ? yaml.parse(response.data) : response.data;
58
+ spec = typeof response.data === "string" ? yaml.parse(response.data) : response.data;
60
59
  }
61
- const content = await (0, promises_1.readFile)(specSource, "utf-8");
62
- // Handle both JSON and YAML formats
63
- return specSource.endsWith(".json") ? JSON.parse(content) : yaml.parse(content);
60
+ else {
61
+ const content = await (0, promises_1.readFile)(specSource, "utf-8");
62
+ spec = specSource.endsWith(".json") ? JSON.parse(content) : yaml.parse(content);
63
+ }
64
+ // Convert Swagger 2.0 to OpenAPI 3.0 if needed
65
+ if (spec.swagger === "2.0") {
66
+ return new Promise((resolve, reject) => {
67
+ (0, swagger2openapi_1.convertObj)(spec, {}, (err, result) => {
68
+ if (err)
69
+ reject(err);
70
+ else
71
+ resolve(result.openapi);
72
+ });
73
+ });
74
+ }
75
+ return spec;
64
76
  }
65
77
  catch (error) {
66
78
  if (error instanceof Error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-query-lightbase-codegen",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "license": "MIT",
5
5
  "description": "Generate Axios API clients and React Query options from OpenAPI specifications",
6
6
  "exports": "./dist/index.js",
@@ -34,14 +34,16 @@
34
34
  "release": "release-it"
35
35
  },
36
36
  "dependencies": {
37
- "axios": "^1.7.9",
37
+ "axios": "^1.7.0",
38
38
  "openapi-types": "^12.1.3",
39
+ "swagger2openapi": "^7.0.8",
39
40
  "yaml": "^2.7.0"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@biomejs/biome": "1.9.4",
43
44
  "@tanstack/react-query": "^5.66.9",
44
45
  "@types/node": "^22.13.5",
46
+ "@types/swagger2openapi": "^7.0.4",
45
47
  "release-it": "^17.0.0",
46
48
  "ts-node": "^10.9.2",
47
49
  "typescript": "^5.7.3"
@@ -52,7 +52,8 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
52
52
  const contentType =
53
53
  responseObj.content?.["application/ld+json"]?.schema ??
54
54
  responseObj.content?.["application/json"]?.schema ??
55
- responseObj.content?.["application/octet-stream"]?.schema;
55
+ responseObj.content?.["application/octet-stream"]?.schema ??
56
+ responseObj.content?.["application/json;charset=UTF-8"]?.schema;
56
57
 
57
58
  const typeName = pascalCase(`${operationId}Response${code}`);
58
59
 
@@ -81,7 +82,8 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
81
82
  requestBody && "content" in requestBody
82
83
  ? (requestBody.content?.["application/ld+json"]?.schema ??
83
84
  requestBody.content?.["application/json"]?.schema ??
84
- requestBody.content?.["application/octet-stream"]?.schema)
85
+ requestBody.content?.["application/octet-stream"]?.schema ??
86
+ requestBody.content?.["application/json;charset=UTF-8"]?.schema)
85
87
  : undefined;
86
88
 
87
89
  const requestBodySchema = content ? resolveSchema(content, spec) : undefined;
@@ -101,7 +103,7 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
101
103
  const urlWithParams = urlParams.length > 0 ? `\`${path.replace(/{(\w+)}/g, "${data.$1}")}\`` : `"${path}"`;
102
104
 
103
105
  const methodBody = [
104
- `${hasData ? "const { axiosConfig, ...data } = props || {};" : "const { axiosConfig } = props || {};"}`,
106
+ `${hasData ? "const { axiosConfig = {}, ...data } = props || {};" : "const { axiosConfig } = props || {};"}`,
105
107
  "const apiClient = getApiClient();",
106
108
  `const url = ${urlWithParams};`,
107
109
  queryParams.length > 0
@@ -117,29 +119,35 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
117
119
  };`
118
120
  : "",
119
121
  formDataSchema?.properties
120
- ? `const formData = new FormData();
122
+ ? `const bodyData = new FormData();
121
123
  ${Object.entries(formDataSchema.properties)
122
124
  .map(([key, prop]) => {
123
125
  const schemaProperty = prop as OpenAPIV3.SchemaObject;
124
126
  const isBinary = schemaProperty.format === "binary";
125
127
  return formDataSchema?.required?.includes(key)
126
- ? `formData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});`
128
+ ? `bodyData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});`
127
129
  : `if (${queryParams.length > 0 ? "bodyData" : "data"}.${key} != null) {
128
- formData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});
130
+ bodyData.append("${key}", ${isBinary ? "" : "String("}${queryParams.length > 0 ? "bodyData" : "data"}.${key}${isBinary ? "" : ")"});
129
131
  }`;
130
132
  })
131
133
  .join("\n ")}`
132
134
  : "",
133
- `const res = await apiClient.${method}<${responseType}>(url, {
134
- ${queryParams.length > 0 ? "params: queryData," : ""}
135
- ${requestBody ? `data: ${isFormData ? "formData" : "bodyData"},` : ""}
136
- ${isFormData ? `config: { headers: { 'Content-Type': 'multipart/form-data', ...axiosConfig?.headers }, ...axiosConfig },` : "...axiosConfig"}
137
- });
138
- return res.data;`,
135
+ queryParams.length > 0 ? "axiosConfig.params = queryData;" : "",
136
+ isFormData
137
+ ? "axiosConfig.headers = { ...axiosConfig.headers, 'Content-Type': 'multipart/form-data' };"
138
+ : "",
139
+ requestBody
140
+ ? `const res = await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties ? "bodyData" : "data"}, axiosConfig);`
141
+ : `const res = await apiClient.${method}<${responseType}>(url, axiosConfig);`,
142
+ "return res.data;",
139
143
  ]
140
144
  .filter(Boolean)
141
145
  .join("\n ");
142
146
 
147
+ // ${queryParams.length > 0 ? "params: queryData," : ""}
148
+ // ${requestBody ? `data: ${isFormData ? "formData" : "bodyData"},` : ""}
149
+ // ${isFormData ? `config: { headers: { 'Content-Type': 'multipart/form-data', ...axiosConfig?.headers }, ...axiosConfig },` : "...axiosConfig"}
150
+
143
151
  const requestParms = hasData
144
152
  ? `props: T.${pascalCase(operationId)}Params & { axiosConfig?: AxiosRequestConfig; }`
145
153
  : "props?: { axiosConfig?: AxiosRequestConfig }";
@@ -58,7 +58,8 @@ export function generateTypeDefinitions(spec: OpenAPIV3.Document): string {
58
58
  content["application/ld+json"] ??
59
59
  content["application/json"] ??
60
60
  content["multipart/form-data"] ??
61
- content["application/octet-stream"];
61
+ content["application/octet-stream"] ??
62
+ content["application/json;charset=UTF-8"];
62
63
  if (jsonContent?.schema) {
63
64
  const typeName = `${operationId}Request`;
64
65
  output += generateTypeDefinition(typeName, jsonContent.schema as OpenAPIV3.SchemaObject);
@@ -72,7 +73,8 @@ export function generateTypeDefinitions(spec: OpenAPIV3.Document): string {
72
73
  const content =
73
74
  responseObj.content?.["application/ld+json"] ??
74
75
  responseObj.content?.["application/json"] ??
75
- responseObj.content?.["application/octet-stream"];
76
+ responseObj.content?.["application/octet-stream"] ??
77
+ responseObj.content?.["application/json;charset=UTF-8"];
76
78
  if (content?.schema) {
77
79
  const typeName = `${operationId}Response${code}`;
78
80
  output += generateTypeDefinition(typeName, content.schema as OpenAPIV3.SchemaObject);
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
3
  import axios from "axios";
4
4
  import type { OpenAPIV3 } from "openapi-types";
5
+ import { convert, convertObj } from "swagger2openapi";
5
6
  import * as yaml from "yaml";
6
7
  import { generateApiClient } from "./generator/clientGenerator";
7
8
  import { generateInstance } from "./generator/instanceGenerator";
@@ -15,19 +16,27 @@ import { specTitle } from "./utils";
15
16
  */
16
17
  async function loadOpenAPISpec(specSource: string): Promise<OpenAPIV3.Document> {
17
18
  try {
19
+ let spec: any;
20
+
18
21
  if (specSource.startsWith("http")) {
19
22
  const response = await axios.get(specSource);
20
- // Check if response is YAML by looking for common YAML indicators
21
- const isYaml =
22
- typeof response.data === "string" &&
23
- (response.data.trim().startsWith("openapi:") || response.data.trim().startsWith("swagger:"));
23
+ spec = typeof response.data === "string" ? yaml.parse(response.data) : response.data;
24
+ } else {
25
+ const content = await readFile(specSource, "utf-8");
26
+ spec = specSource.endsWith(".json") ? JSON.parse(content) : yaml.parse(content);
27
+ }
24
28
 
25
- return isYaml ? yaml.parse(response.data) : response.data;
29
+ // Convert Swagger 2.0 to OpenAPI 3.0 if needed
30
+ if (spec.swagger === "2.0") {
31
+ return new Promise((resolve, reject) => {
32
+ convertObj(spec, {}, (err, result) => {
33
+ if (err) reject(err);
34
+ else resolve(result.openapi);
35
+ });
36
+ });
26
37
  }
27
38
 
28
- const content = await readFile(specSource, "utf-8");
29
- // Handle both JSON and YAML formats
30
- return specSource.endsWith(".json") ? JSON.parse(content) : yaml.parse(content);
39
+ return spec;
31
40
  } catch (error) {
32
41
  if (error instanceof Error) {
33
42
  throw new Error(`Failed to load OpenAPI spec: ${error.message}`);