hono-openapi 1.1.0 → 1.1.2

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/index.cjs CHANGED
@@ -75,6 +75,8 @@ function mergeSpecs(route, ...specs) {
75
75
  const values = [...prev[key] ?? [], ...value];
76
76
  if (key === "tags") {
77
77
  prev[key] = Array.from(new Set(values));
78
+ } else if (key === "parameters") {
79
+ prev[key] = mergeParameters(values);
78
80
  } else {
79
81
  prev[key] = values;
80
82
  }
@@ -136,57 +138,65 @@ function removeExcludedPaths(paths, ctx) {
136
138
  const newPaths = {};
137
139
  const _exclude = Array.isArray(exclude) ? exclude : [exclude];
138
140
  for (const [key, value] of Object.entries(paths)) {
139
- const isPathExcluded = !_exclude.some((x) => {
141
+ if (value == null) continue;
142
+ const isExplicitlyExcluded = _exclude.some((x) => {
140
143
  if (typeof x === "string") return key === x;
141
144
  return x.test(key);
142
145
  });
143
- const isStaticFileExcluded = excludeStaticFile ? !key.includes(".") || key.includes("{") : true;
144
- if (isPathExcluded && !(key.includes("*") && !key.includes("{")) && isStaticFileExcluded && value != null) {
145
- for (const method of Object.keys(value)) {
146
- const schema = value[method];
147
- if (schema == null) continue;
148
- if (key.includes("{")) {
149
- if (!schema.parameters) schema.parameters = [];
150
- const pathParameters = key.split("/").filter(
151
- (x) => x.startsWith("{") && !schema.parameters.find(
152
- (params) => params.in === "path" && params.name === x.slice(1, x.length - 1)
153
- )
154
- );
155
- for (const param of pathParameters) {
156
- const paramName = param.slice(1, param.length - 1);
157
- const index = schema.parameters.findIndex(
158
- (x) => {
159
- if ("$ref" in x) {
160
- const pos = x.$ref.split("/").pop();
161
- if (pos) {
162
- const param2 = ctx.components.parameters?.[pos];
163
- if (param2 && !("$ref" in param2)) {
164
- return param2.in === "path" && param2.name === paramName;
165
- }
146
+ if (isExplicitlyExcluded) continue;
147
+ const isWildcardWithoutParameters = key.includes("*") && !key.includes("{");
148
+ if (isWildcardWithoutParameters) continue;
149
+ if (excludeStaticFile) {
150
+ const hasPathParameters = key.includes("{");
151
+ const lastSegment = key.split("/").pop() || "";
152
+ const looksLikeStaticFile = lastSegment.includes(".");
153
+ const shouldExcludeAsStaticFile = !hasPathParameters && looksLikeStaticFile;
154
+ if (shouldExcludeAsStaticFile) continue;
155
+ }
156
+ for (const method of Object.keys(value)) {
157
+ const schema = value[method];
158
+ if (schema == null) continue;
159
+ if (key.includes("{")) {
160
+ schema.parameters = schema.parameters ? [...schema.parameters] : [];
161
+ const pathParameters = key.split("/").filter(
162
+ (x) => x.startsWith("{") && !schema.parameters.find(
163
+ (params) => params.in === "path" && params.name === x.slice(1, x.length - 1)
164
+ )
165
+ );
166
+ for (const param of pathParameters) {
167
+ const paramName = param.slice(1, param.length - 1);
168
+ const index = schema.parameters.findIndex(
169
+ (x) => {
170
+ if ("$ref" in x) {
171
+ const pos = x.$ref.split("/").pop();
172
+ if (pos) {
173
+ const param2 = ctx.components.parameters?.[pos];
174
+ if (param2 && !("$ref" in param2)) {
175
+ return param2.in === "path" && param2.name === paramName;
166
176
  }
167
- return false;
168
177
  }
169
- return x.in === "path" && x.name === paramName;
178
+ return false;
170
179
  }
171
- );
172
- if (index === -1) {
173
- schema.parameters.push({
174
- schema: { type: "string" },
175
- in: "path",
176
- name: paramName,
177
- required: true
178
- });
180
+ return x.in === "path" && x.name === paramName;
179
181
  }
182
+ );
183
+ if (index === -1) {
184
+ schema.parameters.push({
185
+ schema: { type: "string" },
186
+ in: "path",
187
+ name: paramName,
188
+ required: true
189
+ });
180
190
  }
181
191
  }
182
- if (!schema.responses) {
183
- schema.responses = {
184
- 200: {}
185
- };
186
- }
187
192
  }
188
- newPaths[key] = value;
193
+ if (!schema.responses) {
194
+ schema.responses = {
195
+ 200: {}
196
+ };
197
+ }
189
198
  }
199
+ newPaths[key] = value;
190
200
  }
191
201
  return newPaths;
192
202
  }
package/dist/index.d.cts CHANGED
@@ -121,9 +121,9 @@ type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
121
121
  });
122
122
  };
123
123
  type Num<T> = T extends `${infer N extends number}` ? N : T;
124
- type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = {
125
- [K in keyof T]: T[K] extends StandardSchemaV1 ? PromiseOr<TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never>> : never;
126
- }[keyof T];
124
+ type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = PromiseOr<{
125
+ [K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never> : never;
126
+ }[keyof T]>;
127
127
  type Handler<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = (c: Context<E, P, I>, next: Next) => HandlerResponse<T>;
128
128
  declare function describeResponse<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>>(handler: Handler<E, P, I, T>, responses: ResponseObject<T>, options?: Record<string, unknown>): Handler<E, P, I, T>;
129
129
 
@@ -165,7 +165,7 @@ type GenerateSpecOptions = {
165
165
  */
166
166
  includeEmptyPaths: boolean;
167
167
  /**
168
- * Determine if Swagger should exclude static files.
168
+ * Determine if Swagger should exclude static files (by checking if the last path segment contains a period).
169
169
  *
170
170
  * @default true
171
171
  */
package/dist/index.d.ts CHANGED
@@ -121,9 +121,9 @@ type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
121
121
  });
122
122
  };
123
123
  type Num<T> = T extends `${infer N extends number}` ? N : T;
124
- type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = {
125
- [K in keyof T]: T[K] extends StandardSchemaV1 ? PromiseOr<TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never>> : never;
126
- }[keyof T];
124
+ type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = PromiseOr<{
125
+ [K in keyof T]: T[K] extends StandardSchemaV1 ? TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never> : never;
126
+ }[keyof T]>;
127
127
  type Handler<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = (c: Context<E, P, I>, next: Next) => HandlerResponse<T>;
128
128
  declare function describeResponse<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>>(handler: Handler<E, P, I, T>, responses: ResponseObject<T>, options?: Record<string, unknown>): Handler<E, P, I, T>;
129
129
 
@@ -165,7 +165,7 @@ type GenerateSpecOptions = {
165
165
  */
166
166
  includeEmptyPaths: boolean;
167
167
  /**
168
- * Determine if Swagger should exclude static files.
168
+ * Determine if Swagger should exclude static files (by checking if the last path segment contains a period).
169
169
  *
170
170
  * @default true
171
171
  */
package/dist/index.js CHANGED
@@ -73,6 +73,8 @@ function mergeSpecs(route, ...specs) {
73
73
  const values = [...prev[key] ?? [], ...value];
74
74
  if (key === "tags") {
75
75
  prev[key] = Array.from(new Set(values));
76
+ } else if (key === "parameters") {
77
+ prev[key] = mergeParameters(values);
76
78
  } else {
77
79
  prev[key] = values;
78
80
  }
@@ -134,57 +136,65 @@ function removeExcludedPaths(paths, ctx) {
134
136
  const newPaths = {};
135
137
  const _exclude = Array.isArray(exclude) ? exclude : [exclude];
136
138
  for (const [key, value] of Object.entries(paths)) {
137
- const isPathExcluded = !_exclude.some((x) => {
139
+ if (value == null) continue;
140
+ const isExplicitlyExcluded = _exclude.some((x) => {
138
141
  if (typeof x === "string") return key === x;
139
142
  return x.test(key);
140
143
  });
141
- const isStaticFileExcluded = excludeStaticFile ? !key.includes(".") || key.includes("{") : true;
142
- if (isPathExcluded && !(key.includes("*") && !key.includes("{")) && isStaticFileExcluded && value != null) {
143
- for (const method of Object.keys(value)) {
144
- const schema = value[method];
145
- if (schema == null) continue;
146
- if (key.includes("{")) {
147
- if (!schema.parameters) schema.parameters = [];
148
- const pathParameters = key.split("/").filter(
149
- (x) => x.startsWith("{") && !schema.parameters.find(
150
- (params) => params.in === "path" && params.name === x.slice(1, x.length - 1)
151
- )
152
- );
153
- for (const param of pathParameters) {
154
- const paramName = param.slice(1, param.length - 1);
155
- const index = schema.parameters.findIndex(
156
- (x) => {
157
- if ("$ref" in x) {
158
- const pos = x.$ref.split("/").pop();
159
- if (pos) {
160
- const param2 = ctx.components.parameters?.[pos];
161
- if (param2 && !("$ref" in param2)) {
162
- return param2.in === "path" && param2.name === paramName;
163
- }
144
+ if (isExplicitlyExcluded) continue;
145
+ const isWildcardWithoutParameters = key.includes("*") && !key.includes("{");
146
+ if (isWildcardWithoutParameters) continue;
147
+ if (excludeStaticFile) {
148
+ const hasPathParameters = key.includes("{");
149
+ const lastSegment = key.split("/").pop() || "";
150
+ const looksLikeStaticFile = lastSegment.includes(".");
151
+ const shouldExcludeAsStaticFile = !hasPathParameters && looksLikeStaticFile;
152
+ if (shouldExcludeAsStaticFile) continue;
153
+ }
154
+ for (const method of Object.keys(value)) {
155
+ const schema = value[method];
156
+ if (schema == null) continue;
157
+ if (key.includes("{")) {
158
+ schema.parameters = schema.parameters ? [...schema.parameters] : [];
159
+ const pathParameters = key.split("/").filter(
160
+ (x) => x.startsWith("{") && !schema.parameters.find(
161
+ (params) => params.in === "path" && params.name === x.slice(1, x.length - 1)
162
+ )
163
+ );
164
+ for (const param of pathParameters) {
165
+ const paramName = param.slice(1, param.length - 1);
166
+ const index = schema.parameters.findIndex(
167
+ (x) => {
168
+ if ("$ref" in x) {
169
+ const pos = x.$ref.split("/").pop();
170
+ if (pos) {
171
+ const param2 = ctx.components.parameters?.[pos];
172
+ if (param2 && !("$ref" in param2)) {
173
+ return param2.in === "path" && param2.name === paramName;
164
174
  }
165
- return false;
166
175
  }
167
- return x.in === "path" && x.name === paramName;
176
+ return false;
168
177
  }
169
- );
170
- if (index === -1) {
171
- schema.parameters.push({
172
- schema: { type: "string" },
173
- in: "path",
174
- name: paramName,
175
- required: true
176
- });
178
+ return x.in === "path" && x.name === paramName;
177
179
  }
180
+ );
181
+ if (index === -1) {
182
+ schema.parameters.push({
183
+ schema: { type: "string" },
184
+ in: "path",
185
+ name: paramName,
186
+ required: true
187
+ });
178
188
  }
179
189
  }
180
- if (!schema.responses) {
181
- schema.responses = {
182
- 200: {}
183
- };
184
- }
185
190
  }
186
- newPaths[key] = value;
191
+ if (!schema.responses) {
192
+ schema.responses = {
193
+ 200: {}
194
+ };
195
+ }
187
196
  }
197
+ newPaths[key] = value;
188
198
  }
189
199
  return newPaths;
190
200
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hono-openapi",
3
3
  "description": "OpenAPI schema generator for Hono",
4
- "version": "1.1.0",
4
+ "version": "1.1.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -41,9 +41,9 @@
41
41
  }
42
42
  },
43
43
  "peerDependencies": {
44
- "@hono/standard-validator": "^0.1.2",
44
+ "@hono/standard-validator": "^0.2.0",
45
45
  "@standard-community/standard-json": "^0.3.5",
46
- "@standard-community/standard-openapi": "^0.2.8",
46
+ "@standard-community/standard-openapi": "^0.2.9",
47
47
  "@types/json-schema": "^7.0.15",
48
48
  "hono": "^4.8.3",
49
49
  "openapi-types": "^12.1.3"