react-query-lightbase-codegen 2.5.11 → 3.0.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.
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +180 -0
- package/dist/generateHooks.js +14 -57
- package/dist/generateHooks.js.map +1 -1
- package/dist/generator/clientGenerator.d.ts +0 -10
- package/dist/generator/clientGenerator.js +18 -72
- package/dist/generator/reactQueryGenerator.js +4 -40
- package/dist/generator/schemaGenerator.js +37 -51
- package/dist/utils.d.ts +34 -1
- package/dist/utils.js +112 -10
- package/dist/utils.js.map +1 -1
- package/package.json +4 -1
- package/src/cli.ts +212 -0
- package/src/generator/clientGenerator.ts +28 -98
- package/src/generator/reactQueryGenerator.ts +11 -46
- package/src/generator/schemaGenerator.ts +48 -62
- package/src/utils.ts +137 -11
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateTypeDefinitions = generateTypeDefinitions;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
|
+
/**
|
|
6
|
+
* Formats a parameter as a TypeScript property string with optional JSDoc.
|
|
7
|
+
*/
|
|
8
|
+
function formatParamProperty(param, forceRequired = false) {
|
|
9
|
+
const safeName = (0, utils_1.sanitizePropertyName)(param.name);
|
|
10
|
+
const isDeprecated = param.deprecated;
|
|
11
|
+
const hasDescription = param.description;
|
|
12
|
+
const isOptional = forceRequired ? false : !param.required;
|
|
13
|
+
const desc = hasDescription || isDeprecated
|
|
14
|
+
? `/**${hasDescription ? `\n * ${param.description}` : ""}${isDeprecated ? "\n * @deprecated" : ""}\n */\n`
|
|
15
|
+
: "";
|
|
16
|
+
return `${desc}${safeName}${isOptional ? "?" : ""}: ${(0, utils_1.getTypeFromSchema)(param.schema)}`;
|
|
17
|
+
}
|
|
5
18
|
function generateTypeDefinition(name, schema) {
|
|
6
19
|
const description = !("$ref" in schema) && schema.description ? `/**\n * ${schema.description}\n */\n` : "";
|
|
7
20
|
const typeValue = (0, utils_1.getTypeFromSchema)(schema);
|
|
@@ -16,17 +29,15 @@ function generateTypeDefinition(name, schema) {
|
|
|
16
29
|
* Generates TypeScript interface definitions from OpenAPI schemas
|
|
17
30
|
*/
|
|
18
31
|
function generateTypeDefinitions(spec) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
generatedTypes: new Set(),
|
|
22
|
-
};
|
|
32
|
+
const schemas = spec.components?.schemas || {};
|
|
33
|
+
const generatedTypes = new Set();
|
|
23
34
|
let output = "/* Generated TypeScript Definitions */\n\n";
|
|
24
35
|
// Generate types for all schema definitions
|
|
25
|
-
for (const [name, schema] of Object.entries(
|
|
26
|
-
if (
|
|
36
|
+
for (const [name, schema] of Object.entries(schemas)) {
|
|
37
|
+
if (generatedTypes.has(name))
|
|
27
38
|
continue;
|
|
28
39
|
output += generateTypeDefinition(name, schema);
|
|
29
|
-
|
|
40
|
+
generatedTypes.add(name);
|
|
30
41
|
}
|
|
31
42
|
// Generate request/response types
|
|
32
43
|
if (spec.paths) {
|
|
@@ -42,30 +53,32 @@ function generateTypeDefinitions(spec) {
|
|
|
42
53
|
// Generate request body type
|
|
43
54
|
if (requestBody) {
|
|
44
55
|
const content = requestBody.content;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
content["multipart/form-data"] ??
|
|
48
|
-
content["application/octet-stream"] ??
|
|
49
|
-
content["application/json;charset=UTF-8"];
|
|
50
|
-
if (jsonContent?.schema) {
|
|
56
|
+
const requestSchema = (0, utils_1.getContentSchema)(content);
|
|
57
|
+
if (requestSchema) {
|
|
51
58
|
const typeName = `${operationId}Request`;
|
|
52
|
-
output += generateTypeDefinition(typeName,
|
|
59
|
+
output += generateTypeDefinition(typeName, requestSchema);
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
// Generate response types
|
|
63
|
+
const errorTypes = [];
|
|
56
64
|
if (responses) {
|
|
57
65
|
for (const [code, response] of Object.entries(responses)) {
|
|
58
66
|
const responseObj = response;
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
responseObj.content?.["application/octet-stream"] ??
|
|
62
|
-
responseObj.content?.["application/json;charset=UTF-8"];
|
|
63
|
-
if (content?.schema) {
|
|
67
|
+
const responseSchema = (0, utils_1.getContentSchema)(responseObj.content);
|
|
68
|
+
if (responseSchema) {
|
|
64
69
|
const typeName = `${operationId}Response${code}`;
|
|
65
|
-
output += generateTypeDefinition(typeName,
|
|
70
|
+
output += generateTypeDefinition(typeName, responseSchema);
|
|
71
|
+
// Track non-2xx responses for error union type
|
|
72
|
+
if (!code.startsWith("2")) {
|
|
73
|
+
errorTypes.push(typeName);
|
|
74
|
+
}
|
|
66
75
|
}
|
|
67
76
|
}
|
|
68
77
|
}
|
|
78
|
+
// Generate error union type if there are error responses
|
|
79
|
+
if (errorTypes.length > 0) {
|
|
80
|
+
output += `export type ${(0, utils_1.pascalCase)(operationId)}Error = ${errorTypes.join(" | ")};\n\n`;
|
|
81
|
+
}
|
|
69
82
|
// Build data type parts
|
|
70
83
|
const dataProps = [];
|
|
71
84
|
const urlParams = (parameters?.filter((p) => "in" in p && p.in === "path") ||
|
|
@@ -74,37 +87,10 @@ function generateTypeDefinitions(spec) {
|
|
|
74
87
|
[]);
|
|
75
88
|
const headerParams = (parameters?.filter((p) => "in" in p && p.in === "header") ||
|
|
76
89
|
[]);
|
|
77
|
-
// Add path and
|
|
78
|
-
urlParams.forEach((p) =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const hasDescription = "description" in p && p.description;
|
|
82
|
-
const desc = hasDescription || isDeprecated
|
|
83
|
-
? `/**${hasDescription ? `\n* ${p.description}` : ""}${isDeprecated ? "\n* @deprecated" : ""}
|
|
84
|
-
*/\n`
|
|
85
|
-
: "";
|
|
86
|
-
dataProps.push(`${desc}${safeName}: ${(0, utils_1.getTypeFromSchema)(p.schema)}`);
|
|
87
|
-
});
|
|
88
|
-
queryParams.forEach((p) => {
|
|
89
|
-
const safeName = (0, utils_1.sanitizePropertyName)(p.name);
|
|
90
|
-
const isDeprecated = "deprecated" in p && p.deprecated;
|
|
91
|
-
const hasDescription = "description" in p && p.description;
|
|
92
|
-
const desc = hasDescription || isDeprecated
|
|
93
|
-
? `\n/**${hasDescription ? `\n* ${p.description}` : ""}${isDeprecated ? "\n* @deprecated" : ""}
|
|
94
|
-
*/\n`
|
|
95
|
-
: "";
|
|
96
|
-
dataProps.push(`${desc}${safeName}${p.required ? "" : "?"}: ${(0, utils_1.getTypeFromSchema)(p.schema)}`);
|
|
97
|
-
});
|
|
98
|
-
headerParams.forEach((p) => {
|
|
99
|
-
const safeName = (0, utils_1.sanitizePropertyName)(p.name);
|
|
100
|
-
const isDeprecated = "deprecated" in p && p.deprecated;
|
|
101
|
-
const hasDescription = "description" in p && p.description;
|
|
102
|
-
const desc = hasDescription || isDeprecated
|
|
103
|
-
? `\n/**${hasDescription ? `\n* ${p.description}` : ""}${isDeprecated ? "\n* @deprecated" : ""}
|
|
104
|
-
*/\n`
|
|
105
|
-
: "";
|
|
106
|
-
dataProps.push(`${desc}${safeName}${p.required ? "" : "?"}: ${(0, utils_1.getTypeFromSchema)(p.schema)}`);
|
|
107
|
-
});
|
|
90
|
+
// Add path, query, and header parameters
|
|
91
|
+
urlParams.forEach((p) => dataProps.push(formatParamProperty(p, true))); // Path params always required
|
|
92
|
+
queryParams.forEach((p) => dataProps.push(formatParamProperty(p)));
|
|
93
|
+
headerParams.forEach((p) => dataProps.push(formatParamProperty(p)));
|
|
108
94
|
// Add request body type if it exists
|
|
109
95
|
const hasData = (parameters && parameters.length > 0) || requestBody;
|
|
110
96
|
let dataType = "undefined";
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from "openapi-types";
|
|
2
|
+
/**
|
|
3
|
+
* Supported content types in order of preference
|
|
4
|
+
*/
|
|
5
|
+
export declare const CONTENT_TYPES: readonly ["application/ld+json", "application/json", "multipart/form-data", "application/octet-stream", "application/json;charset=UTF-8"];
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a schema reference to its actual schema object.
|
|
8
|
+
* If the schema is already a concrete schema (not a $ref), returns it as-is.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveSchema(schema: OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject | undefined, spec: OpenAPIV3.Document): OpenAPIV3.SchemaObject | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Extracts the schema from a content object, checking supported content types in order.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getContentSchema(content: {
|
|
15
|
+
[media: string]: OpenAPIV3.MediaTypeObject;
|
|
16
|
+
} | undefined): OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Operation info extracted from OpenAPI paths
|
|
19
|
+
*/
|
|
20
|
+
export interface OperationInfo {
|
|
21
|
+
method: string;
|
|
22
|
+
path: string;
|
|
23
|
+
operationId: string;
|
|
24
|
+
summary?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
parameters: OpenAPIV3.ParameterObject[];
|
|
27
|
+
requestBody?: OpenAPIV3.RequestBodyObject;
|
|
28
|
+
responses: OpenAPIV3.ResponsesObject;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Collects all operations from an OpenAPI spec, resolving parameter and request body references.
|
|
32
|
+
*/
|
|
33
|
+
export declare function collectOperations(spec: OpenAPIV3.Document): OperationInfo[];
|
|
2
34
|
export declare function camelCase(str: string): string;
|
|
3
35
|
export declare function pascalCase(str: string): string;
|
|
4
36
|
/**
|
|
@@ -39,6 +71,7 @@ export declare function specTitle(spec: OpenAPIV3.Document): string;
|
|
|
39
71
|
* Handles:
|
|
40
72
|
* - References ($ref) by extracting the type name
|
|
41
73
|
* - Nullable types by appending "| null"
|
|
74
|
+
* - Composition types (allOf → intersection, oneOf/anyOf → union)
|
|
42
75
|
* - Enums by creating union types of the values
|
|
43
76
|
* - OneOf schemas as union types
|
|
44
77
|
* - Basic types (string, number, boolean)
|
|
@@ -48,7 +81,7 @@ export declare function specTitle(spec: OpenAPIV3.Document): string;
|
|
|
48
81
|
* - Objects with additionalProperties as Records
|
|
49
82
|
* - Fallback to "any" for unknown types
|
|
50
83
|
*
|
|
51
|
-
* @param
|
|
84
|
+
* @param schema - The OpenAPI schema/parameter object to convert
|
|
52
85
|
* @returns The TypeScript type as a string
|
|
53
86
|
*/
|
|
54
87
|
export declare function getTypeFromSchema(schema: OpenAPIV3.ParameterObject | OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined): string | undefined;
|
package/dist/utils.js
CHANGED
|
@@ -1,11 +1,96 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CONTENT_TYPES = void 0;
|
|
4
|
+
exports.resolveSchema = resolveSchema;
|
|
5
|
+
exports.getContentSchema = getContentSchema;
|
|
6
|
+
exports.collectOperations = collectOperations;
|
|
3
7
|
exports.camelCase = camelCase;
|
|
4
8
|
exports.pascalCase = pascalCase;
|
|
5
9
|
exports.sanitizePropertyName = sanitizePropertyName;
|
|
6
10
|
exports.sanitizeTypeName = sanitizeTypeName;
|
|
7
11
|
exports.specTitle = specTitle;
|
|
8
12
|
exports.getTypeFromSchema = getTypeFromSchema;
|
|
13
|
+
/**
|
|
14
|
+
* Supported content types in order of preference
|
|
15
|
+
*/
|
|
16
|
+
exports.CONTENT_TYPES = [
|
|
17
|
+
"application/ld+json",
|
|
18
|
+
"application/json",
|
|
19
|
+
"multipart/form-data",
|
|
20
|
+
"application/octet-stream",
|
|
21
|
+
"application/json;charset=UTF-8",
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Resolves a schema reference to its actual schema object.
|
|
25
|
+
* If the schema is already a concrete schema (not a $ref), returns it as-is.
|
|
26
|
+
*/
|
|
27
|
+
function resolveSchema(schema, spec) {
|
|
28
|
+
if (!schema)
|
|
29
|
+
return undefined;
|
|
30
|
+
if ("$ref" in schema) {
|
|
31
|
+
const index = schema.$ref.split("/").pop();
|
|
32
|
+
return spec.components?.schemas?.[index];
|
|
33
|
+
}
|
|
34
|
+
return schema;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extracts the schema from a content object, checking supported content types in order.
|
|
38
|
+
*/
|
|
39
|
+
function getContentSchema(content) {
|
|
40
|
+
if (!content)
|
|
41
|
+
return undefined;
|
|
42
|
+
for (const type of exports.CONTENT_TYPES) {
|
|
43
|
+
if (content[type]?.schema) {
|
|
44
|
+
return content[type].schema;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const HTTP_METHODS = ["get", "post", "put", "delete", "patch"];
|
|
50
|
+
/**
|
|
51
|
+
* Collects all operations from an OpenAPI spec, resolving parameter and request body references.
|
|
52
|
+
*/
|
|
53
|
+
function collectOperations(spec) {
|
|
54
|
+
const operations = [];
|
|
55
|
+
const resolveParameters = (parameters) => {
|
|
56
|
+
return parameters.map((p) => {
|
|
57
|
+
if ("$ref" in p) {
|
|
58
|
+
const index = p.$ref.split("/").pop();
|
|
59
|
+
return spec.components?.parameters?.[index];
|
|
60
|
+
}
|
|
61
|
+
return p;
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
const resolveRequestBody = (requestBody) => {
|
|
65
|
+
if (!requestBody)
|
|
66
|
+
return undefined;
|
|
67
|
+
if ("$ref" in requestBody) {
|
|
68
|
+
const index = requestBody.$ref.split("/").pop();
|
|
69
|
+
return spec.components?.requestBodies?.[index];
|
|
70
|
+
}
|
|
71
|
+
return requestBody;
|
|
72
|
+
};
|
|
73
|
+
Object.entries(spec.paths || {}).forEach(([path, pathItem]) => {
|
|
74
|
+
if (!pathItem)
|
|
75
|
+
return;
|
|
76
|
+
HTTP_METHODS.forEach((method) => {
|
|
77
|
+
const operation = pathItem[method];
|
|
78
|
+
if (!operation)
|
|
79
|
+
return;
|
|
80
|
+
operations.push({
|
|
81
|
+
method,
|
|
82
|
+
path,
|
|
83
|
+
operationId: sanitizeTypeName(operation.operationId || path.replace(/\W+/g, "_")),
|
|
84
|
+
summary: operation.summary,
|
|
85
|
+
description: operation.description,
|
|
86
|
+
parameters: resolveParameters([...(pathItem.parameters || []), ...(operation.parameters || [])]),
|
|
87
|
+
requestBody: resolveRequestBody(operation.requestBody),
|
|
88
|
+
responses: operation.responses,
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
return operations;
|
|
93
|
+
}
|
|
9
94
|
function camelCase(str) {
|
|
10
95
|
return str
|
|
11
96
|
.replace(/[^a-zA-Z0-9]+(.)/g, (_, chr) => chr.toUpperCase())
|
|
@@ -64,6 +149,7 @@ function specTitle(spec) {
|
|
|
64
149
|
* Handles:
|
|
65
150
|
* - References ($ref) by extracting the type name
|
|
66
151
|
* - Nullable types by appending "| null"
|
|
152
|
+
* - Composition types (allOf → intersection, oneOf/anyOf → union)
|
|
67
153
|
* - Enums by creating union types of the values
|
|
68
154
|
* - OneOf schemas as union types
|
|
69
155
|
* - Basic types (string, number, boolean)
|
|
@@ -73,7 +159,7 @@ function specTitle(spec) {
|
|
|
73
159
|
* - Objects with additionalProperties as Records
|
|
74
160
|
* - Fallback to "any" for unknown types
|
|
75
161
|
*
|
|
76
|
-
* @param
|
|
162
|
+
* @param schema - The OpenAPI schema/parameter object to convert
|
|
77
163
|
* @returns The TypeScript type as a string
|
|
78
164
|
*/
|
|
79
165
|
function getTypeFromSchema(schema) {
|
|
@@ -86,6 +172,30 @@ function getTypeFromSchema(schema) {
|
|
|
86
172
|
}
|
|
87
173
|
// Add "| null" for nullable types
|
|
88
174
|
const nullable = "nullable" in schema && schema.nullable ? " | null" : "";
|
|
175
|
+
// Handle allOf (intersection types)
|
|
176
|
+
if ("allOf" in schema && schema.allOf) {
|
|
177
|
+
const types = schema.allOf.map((s) => getTypeFromSchema(s)).filter(Boolean);
|
|
178
|
+
if (types.length === 0)
|
|
179
|
+
return "any";
|
|
180
|
+
const result = types.length === 1 ? types[0] : `(${types.join(" & ")})`;
|
|
181
|
+
return `${result}${nullable}`;
|
|
182
|
+
}
|
|
183
|
+
// Handle oneOf (union types - exactly one)
|
|
184
|
+
if ("oneOf" in schema && schema.oneOf) {
|
|
185
|
+
const types = schema.oneOf.map((s) => getTypeFromSchema(s)).filter(Boolean);
|
|
186
|
+
if (types.length === 0)
|
|
187
|
+
return "any";
|
|
188
|
+
const result = types.length === 1 ? types[0] : `(${types.join(" | ")})`;
|
|
189
|
+
return `${result}${nullable}`;
|
|
190
|
+
}
|
|
191
|
+
// Handle anyOf (union types - one or more)
|
|
192
|
+
if ("anyOf" in schema && schema.anyOf) {
|
|
193
|
+
const types = schema.anyOf.map((s) => getTypeFromSchema(s)).filter(Boolean);
|
|
194
|
+
if (types.length === 0)
|
|
195
|
+
return "any";
|
|
196
|
+
const result = types.length === 1 ? types[0] : `(${types.join(" | ")})`;
|
|
197
|
+
return `${result}${nullable}`;
|
|
198
|
+
}
|
|
89
199
|
// Handle enums as union types
|
|
90
200
|
if ("enum" in schema && schema.enum) {
|
|
91
201
|
if (Object.values(schema.enum)?.length > 0) {
|
|
@@ -95,13 +205,6 @@ function getTypeFromSchema(schema) {
|
|
|
95
205
|
}
|
|
96
206
|
return schema.enum.map((e) => (typeof e === "string" ? `'${e}'` : e)).join(" | ") + nullable;
|
|
97
207
|
}
|
|
98
|
-
// Handle oneOf as union types
|
|
99
|
-
if ("oneOf" in schema && schema.oneOf) {
|
|
100
|
-
const unionTypes = schema.oneOf
|
|
101
|
-
.map((subSchema) => getTypeFromSchema(subSchema))
|
|
102
|
-
.filter((type) => type !== undefined);
|
|
103
|
-
return unionTypes.length > 0 ? `${unionTypes.join(" | ")}${nullable}` : `any${nullable}`;
|
|
104
|
-
}
|
|
105
208
|
// Handle types based on the "type" property
|
|
106
209
|
if ("type" in schema) {
|
|
107
210
|
switch (schema.type) {
|
|
@@ -132,8 +235,7 @@ function getTypeFromSchema(schema) {
|
|
|
132
235
|
const isDeprecated = "deprecated" in prop && prop.deprecated;
|
|
133
236
|
const hasDescription = "description" in prop && prop.description;
|
|
134
237
|
const desc = hasDescription || isDeprecated
|
|
135
|
-
? `/**${hasDescription ? `\n* ${prop.description}` : ""}${isDeprecated ? "\n* @deprecated" : ""}
|
|
136
|
-
*/\n`
|
|
238
|
+
? `/**${hasDescription ? `\n * ${prop.description}` : ""}${isDeprecated ? "\n * @deprecated" : ""}\n */\n`
|
|
137
239
|
: "";
|
|
138
240
|
return `${desc}${safeName}${isRequired ? "" : "?"}: ${propertyType};`;
|
|
139
241
|
})
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;AACjC,OAAO,OAAO,MAAM,MAAM,CAAC;AAC3B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAgD,EAAE,EAAE,CAC1E,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC/D;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAa,EAA+B,EAAE;IACxE,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAkB,EAAE,EAAE;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,QAAQ,GAAG,QAAQ,CAAC;QAE7B,KAAK,SAAS;YACZ,OAAO,SAAS,GAAG,QAAQ,CAAC;QAE9B,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;QAEnC,KAAK,QAAQ;YACX,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-query-lightbase-codegen",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.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",
|
|
7
|
+
"bin": {
|
|
8
|
+
"react-query-lightbase-codegen": "./dist/cli.js"
|
|
9
|
+
},
|
|
7
10
|
"files": ["src", "dist"],
|
|
8
11
|
"author": {
|
|
9
12
|
"name": "Oliver Winter",
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile, stat } from "node:fs/promises";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { codegenerate } from "./index";
|
|
6
|
+
import type { OpenAPIConfig } from "./types/config";
|
|
7
|
+
|
|
8
|
+
const VERSION = "2.5.11";
|
|
9
|
+
|
|
10
|
+
const HELP = `
|
|
11
|
+
react-query-lightbase-codegen - Generate React Query clients from OpenAPI specs
|
|
12
|
+
|
|
13
|
+
USAGE:
|
|
14
|
+
npx react-query-lightbase-codegen [options] <spec...> -o <output>
|
|
15
|
+
npx react-query-lightbase-codegen --config <config-file>
|
|
16
|
+
|
|
17
|
+
ARGUMENTS:
|
|
18
|
+
<spec...> One or more OpenAPI spec files (local paths or URLs)
|
|
19
|
+
|
|
20
|
+
OPTIONS:
|
|
21
|
+
-o, --output <dir> Output directory for generated files (default: ./generated)
|
|
22
|
+
-c, --config <file> Path to JSON config file
|
|
23
|
+
-h, --help Show this help message
|
|
24
|
+
-v, --version Show version number
|
|
25
|
+
|
|
26
|
+
EXAMPLES:
|
|
27
|
+
# Single local spec
|
|
28
|
+
npx react-query-lightbase-codegen ./api.yaml -o ./src/generated
|
|
29
|
+
|
|
30
|
+
# Remote spec
|
|
31
|
+
npx react-query-lightbase-codegen https://api.example.com/openapi.json -o ./generated
|
|
32
|
+
|
|
33
|
+
# Multiple specs
|
|
34
|
+
npx react-query-lightbase-codegen ./auth.yaml ./users.yaml -o ./generated
|
|
35
|
+
|
|
36
|
+
# Using config file
|
|
37
|
+
npx react-query-lightbase-codegen --config ./codegen.json
|
|
38
|
+
|
|
39
|
+
CONFIG FILE FORMAT:
|
|
40
|
+
{
|
|
41
|
+
"specSource": "./api.yaml", // or ["./auth.yaml", "./users.yaml"]
|
|
42
|
+
"exportDir": "./src/generated"
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
interface ParsedArgs {
|
|
47
|
+
specs: string[];
|
|
48
|
+
output: string;
|
|
49
|
+
config?: string;
|
|
50
|
+
help: boolean;
|
|
51
|
+
version: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseArgs(args: string[]): ParsedArgs {
|
|
55
|
+
const result: ParsedArgs = {
|
|
56
|
+
specs: [],
|
|
57
|
+
output: "./generated",
|
|
58
|
+
help: false,
|
|
59
|
+
version: false,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
let i = 0;
|
|
63
|
+
while (i < args.length) {
|
|
64
|
+
const arg = args[i];
|
|
65
|
+
|
|
66
|
+
switch (arg) {
|
|
67
|
+
case "-h":
|
|
68
|
+
case "--help":
|
|
69
|
+
result.help = true;
|
|
70
|
+
break;
|
|
71
|
+
|
|
72
|
+
case "-v":
|
|
73
|
+
case "--version":
|
|
74
|
+
result.version = true;
|
|
75
|
+
break;
|
|
76
|
+
|
|
77
|
+
case "-o":
|
|
78
|
+
case "--output":
|
|
79
|
+
i++;
|
|
80
|
+
if (i >= args.length) {
|
|
81
|
+
throw new Error("Missing value for --output");
|
|
82
|
+
}
|
|
83
|
+
result.output = args[i];
|
|
84
|
+
break;
|
|
85
|
+
|
|
86
|
+
case "-c":
|
|
87
|
+
case "--config":
|
|
88
|
+
i++;
|
|
89
|
+
if (i >= args.length) {
|
|
90
|
+
throw new Error("Missing value for --config");
|
|
91
|
+
}
|
|
92
|
+
result.config = args[i];
|
|
93
|
+
break;
|
|
94
|
+
|
|
95
|
+
default:
|
|
96
|
+
if (arg.startsWith("-")) {
|
|
97
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
98
|
+
}
|
|
99
|
+
result.specs.push(arg);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
i++;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function loadConfigFile(configPath: string): Promise<OpenAPIConfig> {
|
|
109
|
+
try {
|
|
110
|
+
const content = await readFile(configPath, "utf-8");
|
|
111
|
+
const config = JSON.parse(content);
|
|
112
|
+
|
|
113
|
+
if (!config.specSource) {
|
|
114
|
+
throw new Error("Config file must contain 'specSource'");
|
|
115
|
+
}
|
|
116
|
+
if (!config.exportDir) {
|
|
117
|
+
throw new Error("Config file must contain 'exportDir'");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
specSource: config.specSource,
|
|
122
|
+
exportDir: resolve(process.cwd(), config.exportDir),
|
|
123
|
+
};
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error instanceof Error) {
|
|
126
|
+
throw new Error(`Failed to load config file: ${error.message}`);
|
|
127
|
+
}
|
|
128
|
+
throw new Error("Failed to load config file");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function resolveSpecPath(spec: string): string {
|
|
133
|
+
// Keep URLs as-is
|
|
134
|
+
if (spec.startsWith("http://") || spec.startsWith("https://")) {
|
|
135
|
+
return spec;
|
|
136
|
+
}
|
|
137
|
+
// Resolve local paths relative to cwd
|
|
138
|
+
return resolve(process.cwd(), spec);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function main(): Promise<void> {
|
|
142
|
+
const args = process.argv.slice(2);
|
|
143
|
+
|
|
144
|
+
if (args.length === 0) {
|
|
145
|
+
console.log(HELP);
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let parsed: ParsedArgs;
|
|
150
|
+
try {
|
|
151
|
+
parsed = parseArgs(args);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof Error) {
|
|
154
|
+
console.error(`Error: ${error.message}`);
|
|
155
|
+
}
|
|
156
|
+
console.error("Use --help for usage information");
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (parsed.help) {
|
|
161
|
+
console.log(HELP);
|
|
162
|
+
process.exit(0);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (parsed.version) {
|
|
166
|
+
console.log(`react-query-lightbase-codegen v${VERSION}`);
|
|
167
|
+
process.exit(0);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let config: OpenAPIConfig;
|
|
171
|
+
|
|
172
|
+
if (parsed.config) {
|
|
173
|
+
// Load from config file
|
|
174
|
+
config = await loadConfigFile(parsed.config);
|
|
175
|
+
} else {
|
|
176
|
+
// Build config from CLI args
|
|
177
|
+
if (parsed.specs.length === 0) {
|
|
178
|
+
console.error("Error: No spec files provided");
|
|
179
|
+
console.error("Use --help for usage information");
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const resolvedSpecs = parsed.specs.map(resolveSpecPath);
|
|
184
|
+
|
|
185
|
+
config = {
|
|
186
|
+
specSource: resolvedSpecs.length === 1 ? resolvedSpecs[0] : resolvedSpecs,
|
|
187
|
+
exportDir: resolve(process.cwd(), parsed.output),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
console.log("Generating API client...");
|
|
193
|
+
console.log(
|
|
194
|
+
` Specs: ${Array.isArray(config.specSource) ? config.specSource.join(", ") : config.specSource}`
|
|
195
|
+
);
|
|
196
|
+
console.log(` Output: ${config.exportDir}`);
|
|
197
|
+
console.log("");
|
|
198
|
+
|
|
199
|
+
await codegenerate(config);
|
|
200
|
+
|
|
201
|
+
console.log("Generation complete!");
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (error instanceof Error) {
|
|
204
|
+
console.error(`Error: ${error.message}`);
|
|
205
|
+
} else {
|
|
206
|
+
console.error("An unknown error occurred");
|
|
207
|
+
}
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
main();
|