react-query-lightbase-codegen 3.0.0 → 3.1.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.
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateApiClient = generateApiClient;
4
4
  const utils_1 = require("../utils");
5
5
  function generateAxiosMethod(operation, spec) {
6
- const { method, path, operationId, summary, description, parameters, requestBody, responses } = operation;
6
+ const { method, path, operationId, summary, description, deprecated, parameters, requestBody, responses } = operation;
7
7
  // Generate JSDoc
8
8
  const jsDocLines = ["/**"];
9
+ if (deprecated)
10
+ jsDocLines.push(" * @deprecated");
9
11
  if (summary)
10
12
  jsDocLines.push(` * ${summary}`);
11
13
  if (description)
@@ -19,14 +21,17 @@ function generateAxiosMethod(operation, spec) {
19
21
  ? "query."
20
22
  : param.in === "header"
21
23
  ? "headers."
22
- : "";
24
+ : param.in === "cookie"
25
+ ? "cookies."
26
+ : "";
23
27
  jsDocLines.push(` * @param ${prefix}${param.name}${desc}`);
24
28
  });
25
29
  if (requestBody && "description" in requestBody) {
26
30
  jsDocLines.push(` * @param data - ${requestBody.description}`);
27
31
  }
28
- // Add return type description
29
- const responseDetails = Object.entries(responses).find(([code]) => code.startsWith("2"));
32
+ // Add return type description - prefer 2xx responses, fall back to "default"
33
+ const responseDetails = Object.entries(responses).find(([code]) => code.startsWith("2")) ||
34
+ Object.entries(responses).find(([code]) => code === "default");
30
35
  if (responseDetails) {
31
36
  const [code, response] = responseDetails;
32
37
  const responseObj = response;
@@ -47,6 +52,7 @@ function generateAxiosMethod(operation, spec) {
47
52
  const urlParams = parameters?.filter((p) => p.in === "path") || [];
48
53
  const queryParams = parameters?.filter((p) => p.in === "query") || [];
49
54
  const headerParams = parameters?.filter((p) => p.in === "header") || [];
55
+ const cookieParams = parameters?.filter((p) => p.in === "cookie") || [];
50
56
  const isFormData = requestBody && "content" in requestBody && requestBody.content?.["multipart/form-data"];
51
57
  const formDataSchema = isFormData
52
58
  ? (0, utils_1.resolveSchema)(requestBody.content["multipart/form-data"].schema, spec)
@@ -62,9 +68,20 @@ function generateAxiosMethod(operation, spec) {
62
68
  const hasData = (parameters && parameters.length > 0) || operation.requestBody;
63
69
  const namedType = (0, utils_1.pascalCase)(operationId);
64
70
  // Get response type from 2xx response
65
- const responseType = responseDetails?.[0] && "content" in responseDetails[1]
66
- ? `T.${`${namedType}Response${responseDetails[0]}`}`
67
- : "unknown";
71
+ const responseType = (() => {
72
+ if (!responseDetails)
73
+ return "unknown";
74
+ const [code, response] = responseDetails;
75
+ // If response has content, use the generated type
76
+ if ("content" in response && response.content) {
77
+ return `T.${namedType}Response${code}`;
78
+ }
79
+ // 204 (No Content) and 205 (Reset Content) should return void
80
+ if (code === "204" || code === "205") {
81
+ return "void";
82
+ }
83
+ return "unknown";
84
+ })();
68
85
  const urlWithParams = urlParams.length > 0 ? `\`${path.replace(/{(\w+)}/g, "${encodeURIComponent(data.$1)}")}\`` : `"${path}"`;
69
86
  // Handle destructuring based on whether we have primitive request body
70
87
  const destructuringLine = hasData
@@ -106,13 +123,18 @@ function generateAxiosMethod(operation, spec) {
106
123
  headerParams.length > 0
107
124
  ? `axiosConfig.headers = { ...axiosConfig.headers, ${headerParams.map((p) => `["${p.name}"]: data["${p.name}"]`).join(", ")} };`
108
125
  : "",
109
- isFormData
110
- ? "axiosConfig.headers = { ...axiosConfig.headers, 'Content-Type': 'multipart/form-data' };"
126
+ cookieParams.length > 0
127
+ ? `axiosConfig.headers = { ...axiosConfig.headers, Cookie: [${cookieParams.map((p) => `data["${p.name}"] != null ? \`${p.name}=\${data["${p.name}"]}\` : null`).join(", ")}].filter(Boolean).join("; ") };`
111
128
  : "",
129
+ // Note: Don't set Content-Type for FormData - Axios will set it automatically with the correct boundary
112
130
  requestBody
113
- ? `const res = await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties || requestBodySchema?.properties ? "bodyData" : "data"}, axiosConfig);`
114
- : `const res = await apiClient.${method}<${responseType}>(url, axiosConfig);`,
115
- "return res.data;",
131
+ ? responseType === "void"
132
+ ? `await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties || requestBodySchema?.properties ? "bodyData" : "data"}, axiosConfig);`
133
+ : `const res = await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties || requestBodySchema?.properties ? "bodyData" : "data"}, axiosConfig);`
134
+ : responseType === "void"
135
+ ? `await apiClient.${method}<${responseType}>(url, axiosConfig);`
136
+ : `const res = await apiClient.${method}<${responseType}>(url, axiosConfig);`,
137
+ responseType !== "void" ? "return res.data;" : "",
116
138
  ]
117
139
  .filter(Boolean)
118
140
  .join("\n ");
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateReactQuery = generateReactQuery;
4
4
  const utils_1 = require("../utils");
5
5
  function generateQueryOptions(operation, spec) {
6
- const { operationId, parameters, requestBody } = operation;
6
+ const { operationId, parameters, requestBody, deprecated } = operation;
7
7
  const hasData = (parameters && parameters.length > 0) || operation.requestBody;
8
8
  // Helper to get required fields from a schema
9
9
  const getRequiredFields = (schema, context) => {
@@ -56,8 +56,9 @@ function generateQueryOptions(operation, spec) {
56
56
  ? "!!data"
57
57
  : `hasDefinedProps(${paramsVariable}, ${requiredParams.join(", ")})`
58
58
  : "true";
59
+ const deprecatedComment = deprecated ? "/** @deprecated */\n" : "";
59
60
  return `
60
- export const ${namedQueryOptions} = (
61
+ ${deprecatedComment}export const ${namedQueryOptions} = (
61
62
  ${hasData ? `props: Partial<Parameters<typeof apiClient.${namedQuery}>[0]>` : `props?: Partial<Parameters<typeof apiClient.${namedQuery}>[0]>`}
62
63
  ) => {
63
64
  ${destructuringLine}
@@ -72,10 +73,8 @@ function generateReactQuery(spec) {
72
73
  const operations = (0, utils_1.collectOperations)(spec);
73
74
  return `import { queryOptions, skipToken } from '@tanstack/react-query';
74
75
  import * as apiClient from './${(0, utils_1.specTitle)(spec)}.client';
75
- // TEMPORARY: allows for backward compatibility imports
76
- export * from './${(0, utils_1.specTitle)(spec)}.client';
77
76
 
78
- const hasDefinedProps = <T extends { [P in K]?: any }, K extends PropertyKey>(
77
+ const hasDefinedProps = <T extends { [P in K]?: unknown }, K extends PropertyKey>(
79
78
  obj: T,
80
79
  ...keys: K[]
81
80
  ): obj is T & { [P in K]-?: Exclude<T[P], undefined> } => {
@@ -87,10 +87,13 @@ function generateTypeDefinitions(spec) {
87
87
  []);
88
88
  const headerParams = (parameters?.filter((p) => "in" in p && p.in === "header") ||
89
89
  []);
90
- // Add path, query, and header parameters
90
+ const cookieParams = (parameters?.filter((p) => "in" in p && p.in === "cookie") ||
91
+ []);
92
+ // Add path, query, header, and cookie parameters
91
93
  urlParams.forEach((p) => dataProps.push(formatParamProperty(p, true))); // Path params always required
92
94
  queryParams.forEach((p) => dataProps.push(formatParamProperty(p)));
93
95
  headerParams.forEach((p) => dataProps.push(formatParamProperty(p)));
96
+ cookieParams.forEach((p) => dataProps.push(formatParamProperty(p)));
94
97
  // Add request body type if it exists
95
98
  const hasData = (parameters && parameters.length > 0) || requestBody;
96
99
  let dataType = "undefined";
package/dist/utils.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { OpenAPIV3 } from "openapi-types";
2
2
  /**
3
3
  * Supported content types in order of preference
4
4
  */
5
- export declare const CONTENT_TYPES: readonly ["application/ld+json", "application/json", "multipart/form-data", "application/octet-stream", "application/json;charset=UTF-8"];
5
+ export declare const CONTENT_TYPES: readonly ["application/ld+json", "application/json", "text/plain", "multipart/form-data", "application/octet-stream", "application/json;charset=UTF-8"];
6
6
  /**
7
7
  * Resolves a schema reference to its actual schema object.
8
8
  * If the schema is already a concrete schema (not a $ref), returns it as-is.
@@ -23,6 +23,7 @@ export interface OperationInfo {
23
23
  operationId: string;
24
24
  summary?: string;
25
25
  description?: string;
26
+ deprecated?: boolean;
26
27
  parameters: OpenAPIV3.ParameterObject[];
27
28
  requestBody?: OpenAPIV3.RequestBodyObject;
28
29
  responses: OpenAPIV3.ResponsesObject;
package/dist/utils.js CHANGED
@@ -16,6 +16,7 @@ exports.getTypeFromSchema = getTypeFromSchema;
16
16
  exports.CONTENT_TYPES = [
17
17
  "application/ld+json",
18
18
  "application/json",
19
+ "text/plain",
19
20
  "multipart/form-data",
20
21
  "application/octet-stream",
21
22
  "application/json;charset=UTF-8",
@@ -83,6 +84,7 @@ function collectOperations(spec) {
83
84
  operationId: sanitizeTypeName(operation.operationId || path.replace(/\W+/g, "_")),
84
85
  summary: operation.summary,
85
86
  description: operation.description,
87
+ deprecated: operation.deprecated,
86
88
  parameters: resolveParameters([...(pathItem.parameters || []), ...(operation.parameters || [])]),
87
89
  requestBody: resolveRequestBody(operation.requestBody),
88
90
  responses: operation.responses,
@@ -176,7 +178,7 @@ function getTypeFromSchema(schema) {
176
178
  if ("allOf" in schema && schema.allOf) {
177
179
  const types = schema.allOf.map((s) => getTypeFromSchema(s)).filter(Boolean);
178
180
  if (types.length === 0)
179
- return "any";
181
+ return "unknown";
180
182
  const result = types.length === 1 ? types[0] : `(${types.join(" & ")})`;
181
183
  return `${result}${nullable}`;
182
184
  }
@@ -184,7 +186,7 @@ function getTypeFromSchema(schema) {
184
186
  if ("oneOf" in schema && schema.oneOf) {
185
187
  const types = schema.oneOf.map((s) => getTypeFromSchema(s)).filter(Boolean);
186
188
  if (types.length === 0)
187
- return "any";
189
+ return "unknown";
188
190
  const result = types.length === 1 ? types[0] : `(${types.join(" | ")})`;
189
191
  return `${result}${nullable}`;
190
192
  }
@@ -192,7 +194,7 @@ function getTypeFromSchema(schema) {
192
194
  if ("anyOf" in schema && schema.anyOf) {
193
195
  const types = schema.anyOf.map((s) => getTypeFromSchema(s)).filter(Boolean);
194
196
  if (types.length === 0)
195
- return "any";
197
+ return "unknown";
196
198
  const result = types.length === 1 ? types[0] : `(${types.join(" | ")})`;
197
199
  return `${result}${nullable}`;
198
200
  }
@@ -245,16 +247,16 @@ function getTypeFromSchema(schema) {
245
247
  // Handle objects with additionalProperties
246
248
  if (schema.additionalProperties) {
247
249
  const valueType = typeof schema.additionalProperties === "boolean"
248
- ? "any"
250
+ ? "unknown"
249
251
  : getTypeFromSchema(schema.additionalProperties);
250
252
  return `Record<string, ${valueType}>${nullable}`;
251
253
  }
252
254
  // Default object type when no properties specified
253
- return `Record<string, any>${nullable}`;
255
+ return `Record<string, unknown>${nullable}`;
254
256
  default:
255
- return `any${nullable}`;
257
+ return `unknown${nullable}`;
256
258
  }
257
259
  }
258
260
  // Fallback for schemas without a type
259
- return "any";
261
+ return "unknown";
260
262
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-query-lightbase-codegen",
3
- "version": "3.0.0",
3
+ "version": "3.1.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",
@@ -10,9 +10,11 @@ import {
10
10
  } from "../utils";
11
11
 
12
12
  function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document): string {
13
- const { method, path, operationId, summary, description, parameters, requestBody, responses } = operation;
13
+ const { method, path, operationId, summary, description, deprecated, parameters, requestBody, responses } =
14
+ operation;
14
15
  // Generate JSDoc
15
16
  const jsDocLines = ["/**"];
17
+ if (deprecated) jsDocLines.push(" * @deprecated");
16
18
  if (summary) jsDocLines.push(` * ${summary}`);
17
19
  if (description) jsDocLines.push(` * ${description}`);
18
20
 
@@ -26,7 +28,9 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
26
28
  ? "query."
27
29
  : param.in === "header"
28
30
  ? "headers."
29
- : "";
31
+ : param.in === "cookie"
32
+ ? "cookies."
33
+ : "";
30
34
  jsDocLines.push(` * @param ${prefix}${param.name}${desc}`);
31
35
  });
32
36
 
@@ -34,8 +38,10 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
34
38
  jsDocLines.push(` * @param data - ${requestBody.description}`);
35
39
  }
36
40
 
37
- // Add return type description
38
- const responseDetails = Object.entries(responses).find(([code]) => code.startsWith("2"));
41
+ // Add return type description - prefer 2xx responses, fall back to "default"
42
+ const responseDetails =
43
+ Object.entries(responses).find(([code]) => code.startsWith("2")) ||
44
+ Object.entries(responses).find(([code]) => code === "default");
39
45
  if (responseDetails) {
40
46
  const [code, response] = responseDetails;
41
47
  const responseObj = response as OpenAPIV3.ResponseObject;
@@ -58,6 +64,7 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
58
64
  const urlParams = parameters?.filter((p) => p.in === "path") || [];
59
65
  const queryParams = parameters?.filter((p) => p.in === "query") || [];
60
66
  const headerParams = parameters?.filter((p) => p.in === "header") || [];
67
+ const cookieParams = parameters?.filter((p) => p.in === "cookie") || [];
61
68
 
62
69
  const isFormData = requestBody && "content" in requestBody && requestBody.content?.["multipart/form-data"];
63
70
 
@@ -82,11 +89,19 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
82
89
  const namedType = pascalCase(operationId);
83
90
 
84
91
  // Get response type from 2xx response
85
-
86
- const responseType =
87
- responseDetails?.[0] && "content" in responseDetails[1]
88
- ? `T.${`${namedType}Response${responseDetails[0]}`}`
89
- : "unknown";
92
+ const responseType = (() => {
93
+ if (!responseDetails) return "unknown";
94
+ const [code, response] = responseDetails;
95
+ // If response has content, use the generated type
96
+ if ("content" in response && response.content) {
97
+ return `T.${namedType}Response${code}`;
98
+ }
99
+ // 204 (No Content) and 205 (Reset Content) should return void
100
+ if (code === "204" || code === "205") {
101
+ return "void";
102
+ }
103
+ return "unknown";
104
+ })();
90
105
 
91
106
  const urlWithParams =
92
107
  urlParams.length > 0 ? `\`${path.replace(/{(\w+)}/g, "${encodeURIComponent(data.$1)}")}\`` : `"${path}"`;
@@ -134,13 +149,18 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
134
149
  headerParams.length > 0
135
150
  ? `axiosConfig.headers = { ...axiosConfig.headers, ${headerParams.map((p) => `["${p.name}"]: data["${p.name}"]`).join(", ")} };`
136
151
  : "",
137
- isFormData
138
- ? "axiosConfig.headers = { ...axiosConfig.headers, 'Content-Type': 'multipart/form-data' };"
152
+ cookieParams.length > 0
153
+ ? `axiosConfig.headers = { ...axiosConfig.headers, Cookie: [${cookieParams.map((p) => `data["${p.name}"] != null ? \`${p.name}=\${data["${p.name}"]}\` : null`).join(", ")}].filter(Boolean).join("; ") };`
139
154
  : "",
155
+ // Note: Don't set Content-Type for FormData - Axios will set it automatically with the correct boundary
140
156
  requestBody
141
- ? `const res = await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties || requestBodySchema?.properties ? "bodyData" : "data"}, axiosConfig);`
142
- : `const res = await apiClient.${method}<${responseType}>(url, axiosConfig);`,
143
- "return res.data;",
157
+ ? responseType === "void"
158
+ ? `await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties || requestBodySchema?.properties ? "bodyData" : "data"}, axiosConfig);`
159
+ : `const res = await apiClient.${method}<${responseType}>(url, ${formDataSchema?.properties || requestBodySchema?.properties ? "bodyData" : "data"}, axiosConfig);`
160
+ : responseType === "void"
161
+ ? `await apiClient.${method}<${responseType}>(url, axiosConfig);`
162
+ : `const res = await apiClient.${method}<${responseType}>(url, axiosConfig);`,
163
+ responseType !== "void" ? "return res.data;" : "",
144
164
  ]
145
165
  .filter(Boolean)
146
166
  .join("\n ");
@@ -9,7 +9,7 @@ import {
9
9
  } from "../utils";
10
10
 
11
11
  function generateQueryOptions(operation: OperationInfo, spec: OpenAPIV3.Document): string {
12
- const { operationId, parameters, requestBody } = operation;
12
+ const { operationId, parameters, requestBody, deprecated } = operation;
13
13
 
14
14
  const hasData = (parameters && parameters.length > 0) || operation.requestBody;
15
15
 
@@ -78,8 +78,10 @@ function generateQueryOptions(operation: OperationInfo, spec: OpenAPIV3.Document
78
78
  : `hasDefinedProps(${paramsVariable}, ${requiredParams.join(", ")})`
79
79
  : "true";
80
80
 
81
+ const deprecatedComment = deprecated ? "/** @deprecated */\n" : "";
82
+
81
83
  return `
82
- export const ${namedQueryOptions} = (
84
+ ${deprecatedComment}export const ${namedQueryOptions} = (
83
85
  ${hasData ? `props: Partial<Parameters<typeof apiClient.${namedQuery}>[0]>` : `props?: Partial<Parameters<typeof apiClient.${namedQuery}>[0]>`}
84
86
  ) => {
85
87
  ${destructuringLine}
@@ -96,10 +98,8 @@ export function generateReactQuery(spec: OpenAPIV3.Document): string {
96
98
 
97
99
  return `import { queryOptions, skipToken } from '@tanstack/react-query';
98
100
  import * as apiClient from './${specTitle(spec)}.client';
99
- // TEMPORARY: allows for backward compatibility imports
100
- export * from './${specTitle(spec)}.client';
101
101
 
102
- const hasDefinedProps = <T extends { [P in K]?: any }, K extends PropertyKey>(
102
+ const hasDefinedProps = <T extends { [P in K]?: unknown }, K extends PropertyKey>(
103
103
  obj: T,
104
104
  ...keys: K[]
105
105
  ): obj is T & { [P in K]-?: Exclude<T[P], undefined> } => {
@@ -109,11 +109,14 @@ export function generateTypeDefinitions(spec: OpenAPIV3.Document): string {
109
109
  []) as OpenAPIV3.ParameterObject[];
110
110
  const headerParams = (parameters?.filter((p) => "in" in p && p.in === "header") ||
111
111
  []) as OpenAPIV3.ParameterObject[];
112
+ const cookieParams = (parameters?.filter((p) => "in" in p && p.in === "cookie") ||
113
+ []) as OpenAPIV3.ParameterObject[];
112
114
 
113
- // Add path, query, and header parameters
115
+ // Add path, query, header, and cookie parameters
114
116
  urlParams.forEach((p) => dataProps.push(formatParamProperty(p, true))); // Path params always required
115
117
  queryParams.forEach((p) => dataProps.push(formatParamProperty(p)));
116
118
  headerParams.forEach((p) => dataProps.push(formatParamProperty(p)));
119
+ cookieParams.forEach((p) => dataProps.push(formatParamProperty(p)));
117
120
 
118
121
  // Add request body type if it exists
119
122
  const hasData = (parameters && parameters.length > 0) || requestBody;
package/src/utils.ts CHANGED
@@ -6,6 +6,7 @@ import type { OpenAPIV3 } from "openapi-types";
6
6
  export const CONTENT_TYPES = [
7
7
  "application/ld+json",
8
8
  "application/json",
9
+ "text/plain",
9
10
  "multipart/form-data",
10
11
  "application/octet-stream",
11
12
  "application/json;charset=UTF-8",
@@ -51,6 +52,7 @@ export interface OperationInfo {
51
52
  operationId: string;
52
53
  summary?: string;
53
54
  description?: string;
55
+ deprecated?: boolean;
54
56
  parameters: OpenAPIV3.ParameterObject[];
55
57
  requestBody?: OpenAPIV3.RequestBodyObject;
56
58
  responses: OpenAPIV3.ResponsesObject;
@@ -100,6 +102,7 @@ export function collectOperations(spec: OpenAPIV3.Document): OperationInfo[] {
100
102
  operationId: sanitizeTypeName(operation.operationId || path.replace(/\W+/g, "_")),
101
103
  summary: operation.summary,
102
104
  description: operation.description,
105
+ deprecated: operation.deprecated,
103
106
  parameters: resolveParameters([...(pathItem.parameters || []), ...(operation.parameters || [])]),
104
107
  requestBody: resolveRequestBody(operation.requestBody),
105
108
  responses: operation.responses,
@@ -202,7 +205,7 @@ export function getTypeFromSchema(
202
205
  // Handle allOf (intersection types)
203
206
  if ("allOf" in schema && schema.allOf) {
204
207
  const types = schema.allOf.map((s) => getTypeFromSchema(s)).filter(Boolean) as string[];
205
- if (types.length === 0) return "any";
208
+ if (types.length === 0) return "unknown";
206
209
  const result = types.length === 1 ? types[0] : `(${types.join(" & ")})`;
207
210
  return `${result}${nullable}`;
208
211
  }
@@ -210,7 +213,7 @@ export function getTypeFromSchema(
210
213
  // Handle oneOf (union types - exactly one)
211
214
  if ("oneOf" in schema && schema.oneOf) {
212
215
  const types = schema.oneOf.map((s) => getTypeFromSchema(s)).filter(Boolean) as string[];
213
- if (types.length === 0) return "any";
216
+ if (types.length === 0) return "unknown";
214
217
  const result = types.length === 1 ? types[0] : `(${types.join(" | ")})`;
215
218
  return `${result}${nullable}`;
216
219
  }
@@ -218,7 +221,7 @@ export function getTypeFromSchema(
218
221
  // Handle anyOf (union types - one or more)
219
222
  if ("anyOf" in schema && schema.anyOf) {
220
223
  const types = schema.anyOf.map((s) => getTypeFromSchema(s)).filter(Boolean) as string[];
221
- if (types.length === 0) return "any";
224
+ if (types.length === 0) return "unknown";
222
225
  const result = types.length === 1 ? types[0] : `(${types.join(" | ")})`;
223
226
  return `${result}${nullable}`;
224
227
  }
@@ -282,19 +285,19 @@ export function getTypeFromSchema(
282
285
  if (schema.additionalProperties) {
283
286
  const valueType =
284
287
  typeof schema.additionalProperties === "boolean"
285
- ? "any"
288
+ ? "unknown"
286
289
  : getTypeFromSchema(schema.additionalProperties);
287
290
  return `Record<string, ${valueType}>${nullable}`;
288
291
  }
289
292
 
290
293
  // Default object type when no properties specified
291
- return `Record<string, any>${nullable}`;
294
+ return `Record<string, unknown>${nullable}`;
292
295
 
293
296
  default:
294
- return `any${nullable}`;
297
+ return `unknown${nullable}`;
295
298
  }
296
299
  }
297
300
 
298
301
  // Fallback for schemas without a type
299
- return "any";
302
+ return "unknown";
300
303
  }