next-openapi-gen 0.8.5 → 0.8.6
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/README.md +5 -16
- package/dist/lib/route-processor.js +27 -3
- package/dist/lib/schema-processor.js +23 -10
- package/dist/lib/utils.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -842,29 +842,18 @@ Custom schema files support YAML/JSON in OpenAPI 3.0 format. See **[next15-app-m
|
|
|
842
842
|
|
|
843
843
|
## Examples
|
|
844
844
|
|
|
845
|
-
|
|
845
|
+
Explore complete demo projects in the **[examples](./examples/)** directory, covering integrations with Zod, TypeScript, Drizzle and documentation tools like Scalar and Swagger.
|
|
846
846
|
|
|
847
|
-
###
|
|
848
|
-
|
|
849
|
-
| Example | Description | Features |
|
|
850
|
-
| --------------------------------------------------------------- | ----------------------- | ----------------------------------------------- |
|
|
851
|
-
| **[next15-app-zod](./examples/next15-app-zod)** | Zod schemas example | Users, Products, Orders API with Zod validation |
|
|
852
|
-
| **[next15-app-drizzle-zod](./examples/next15-app-drizzle-zod)** | Drizzle-Zod integration | Blog API with Drizzle ORM + drizzle-zod |
|
|
853
|
-
| **[next15-app-mixed-schemas](./examples/next15-app-mixed-schemas)** 🆕 | Multiple schema types | Zod + TypeScript + Custom YAML schemas combined |
|
|
854
|
-
| **[next15-app-typescript](./examples/next15-app-typescript)** | TypeScript types | API with pure TypeScript type definitions |
|
|
855
|
-
| **[next15-app-scalar](./examples/next15-app-scalar)** | Scalar UI | Modern API documentation interface |
|
|
856
|
-
| **[next15-app-swagger](./examples/next15-app-swagger)** | Swagger UI | Classic Swagger documentation |
|
|
857
|
-
|
|
858
|
-
### 🚀 Running Examples
|
|
847
|
+
### 🚀 Run an Example
|
|
859
848
|
|
|
860
849
|
```bash
|
|
861
|
-
cd examples/next15-app-
|
|
850
|
+
cd examples/next15-app-zod
|
|
862
851
|
npm install
|
|
863
|
-
|
|
852
|
+
npx next-openapi-gen generate
|
|
864
853
|
npm run dev
|
|
865
854
|
```
|
|
866
855
|
|
|
867
|
-
|
|
856
|
+
Then open `http://localhost:3000/api-docs` to view the generated docs.
|
|
868
857
|
|
|
869
858
|
## Available UI providers
|
|
870
859
|
|
|
@@ -25,15 +25,39 @@ export class RouteProcessor {
|
|
|
25
25
|
// 1. Add success response
|
|
26
26
|
const successCode = dataTypes.successCode || this.getDefaultSuccessCode(method);
|
|
27
27
|
if (dataTypes.responseType) {
|
|
28
|
-
//
|
|
28
|
+
// Handle array notation (e.g., "Type[]", "Type[][]", "Generic<T>[]")
|
|
29
|
+
let schema;
|
|
30
|
+
let baseType = dataTypes.responseType;
|
|
31
|
+
let arrayDepth = 0;
|
|
32
|
+
// Count and remove array brackets
|
|
33
|
+
while (baseType.endsWith('[]')) {
|
|
34
|
+
arrayDepth++;
|
|
35
|
+
baseType = baseType.slice(0, -2);
|
|
36
|
+
}
|
|
37
|
+
// Ensure the base schema is defined in components/schemas
|
|
29
38
|
this.schemaProcessor.getSchemaContent({
|
|
30
|
-
responseType:
|
|
39
|
+
responseType: baseType,
|
|
31
40
|
});
|
|
41
|
+
// Build schema reference
|
|
42
|
+
if (arrayDepth === 0) {
|
|
43
|
+
// Not an array
|
|
44
|
+
schema = { $ref: `#/components/schemas/${baseType}` };
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Build nested array schema
|
|
48
|
+
schema = { $ref: `#/components/schemas/${baseType}` };
|
|
49
|
+
for (let i = 0; i < arrayDepth; i++) {
|
|
50
|
+
schema = {
|
|
51
|
+
type: "array",
|
|
52
|
+
items: schema,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
32
56
|
responses[successCode] = {
|
|
33
57
|
description: dataTypes.responseDescription || "Successful response",
|
|
34
58
|
content: {
|
|
35
59
|
"application/json": {
|
|
36
|
-
schema:
|
|
60
|
+
schema: schema,
|
|
37
61
|
},
|
|
38
62
|
},
|
|
39
63
|
};
|
|
@@ -825,12 +825,25 @@ export class SchemaProcessor {
|
|
|
825
825
|
};
|
|
826
826
|
}
|
|
827
827
|
getSchemaContent({ tag, paramsType, pathParamsType, bodyType, responseType, }) {
|
|
828
|
+
// Helper function to strip array notation from type names
|
|
829
|
+
const stripArrayNotation = (typeName) => {
|
|
830
|
+
if (!typeName)
|
|
831
|
+
return typeName;
|
|
832
|
+
let baseType = typeName;
|
|
833
|
+
while (baseType.endsWith('[]')) {
|
|
834
|
+
baseType = baseType.slice(0, -2);
|
|
835
|
+
}
|
|
836
|
+
return baseType;
|
|
837
|
+
};
|
|
838
|
+
// Strip array notation for schema lookups
|
|
839
|
+
const baseBodyType = stripArrayNotation(bodyType);
|
|
840
|
+
const baseResponseType = stripArrayNotation(responseType);
|
|
828
841
|
let params = paramsType ? this.openapiDefinitions[paramsType] : {};
|
|
829
842
|
let pathParams = pathParamsType
|
|
830
843
|
? this.openapiDefinitions[pathParamsType]
|
|
831
844
|
: {};
|
|
832
|
-
let body =
|
|
833
|
-
let responses =
|
|
845
|
+
let body = baseBodyType ? this.openapiDefinitions[baseBodyType] : {};
|
|
846
|
+
let responses = baseResponseType ? this.openapiDefinitions[baseResponseType] : {};
|
|
834
847
|
if (paramsType && !params) {
|
|
835
848
|
this.findSchemaDefinition(paramsType, "params");
|
|
836
849
|
params = this.openapiDefinitions[paramsType] || {};
|
|
@@ -839,20 +852,20 @@ export class SchemaProcessor {
|
|
|
839
852
|
this.findSchemaDefinition(pathParamsType, "pathParams");
|
|
840
853
|
pathParams = this.openapiDefinitions[pathParamsType] || {};
|
|
841
854
|
}
|
|
842
|
-
if (
|
|
843
|
-
this.findSchemaDefinition(
|
|
844
|
-
body = this.openapiDefinitions[
|
|
855
|
+
if (baseBodyType && !body) {
|
|
856
|
+
this.findSchemaDefinition(baseBodyType, "body");
|
|
857
|
+
body = this.openapiDefinitions[baseBodyType] || {};
|
|
845
858
|
}
|
|
846
|
-
if (
|
|
847
|
-
this.findSchemaDefinition(
|
|
848
|
-
responses = this.openapiDefinitions[
|
|
859
|
+
if (baseResponseType && !responses) {
|
|
860
|
+
this.findSchemaDefinition(baseResponseType, "response");
|
|
861
|
+
responses = this.openapiDefinitions[baseResponseType] || {};
|
|
849
862
|
}
|
|
850
863
|
if (this.schemaTypes.includes("zod")) {
|
|
851
864
|
const schemasToProcess = [
|
|
852
865
|
paramsType,
|
|
853
866
|
pathParamsType,
|
|
854
|
-
|
|
855
|
-
|
|
867
|
+
baseBodyType,
|
|
868
|
+
baseResponseType,
|
|
856
869
|
].filter(Boolean);
|
|
857
870
|
schemasToProcess.forEach((schemaName) => {
|
|
858
871
|
if (!this.openapiDefinitions[schemaName]) {
|
package/dist/lib/utils.js
CHANGED
|
@@ -159,9 +159,9 @@ export function extractJSDocComments(path) {
|
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
161
|
export function extractTypeFromComment(commentValue, tag) {
|
|
162
|
-
// Updated regex to support generic types with angle brackets
|
|
162
|
+
// Updated regex to support generic types with angle brackets and array brackets
|
|
163
163
|
return (commentValue
|
|
164
|
-
.match(new RegExp(`${tag}\\s*\\s*([\\w<>,\\s]+)`))?.[1]
|
|
164
|
+
.match(new RegExp(`${tag}\\s*\\s*([\\w<>,\\s\\[\\]]+)`))?.[1]
|
|
165
165
|
?.trim() || "");
|
|
166
166
|
}
|
|
167
167
|
export function cleanComment(commentValue) {
|
package/package.json
CHANGED