@smithers-orchestrator/openapi 0.16.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/LICENSE +21 -0
- package/package.json +38 -0
- package/src/HttpMethod.ts +1 -0
- package/src/MediaTypeObject.ts +6 -0
- package/src/OpenApiAuth.ts +16 -0
- package/src/OpenApiSpec.ts +23 -0
- package/src/OpenApiTool.ts +8 -0
- package/src/OpenApiToolsOptions.ts +10 -0
- package/src/OperationObject.ts +14 -0
- package/src/ParameterObject.ts +11 -0
- package/src/ParsedOperation.ts +14 -0
- package/src/PathItem.ts +12 -0
- package/src/RefObject.ts +3 -0
- package/src/RequestBodyObject.ts +7 -0
- package/src/SchemaObject.ts +23 -0
- package/src/_specHelpers.js +65 -0
- package/src/buildOperationSchema.js +63 -0
- package/src/extractOperations.js +50 -0
- package/src/index.d.ts +287 -0
- package/src/index.js +17 -0
- package/src/jsonSchemaToZod.js +197 -0
- package/src/loadSpecEffect.js +51 -0
- package/src/loadSpecSync.js +27 -0
- package/src/metrics.js +19 -0
- package/src/ref-resolver.js +58 -0
- package/src/schema-converter.js +2 -0
- package/src/spec-parser.js +3 -0
- package/src/tool-factory/_helpers.js +237 -0
- package/src/tool-factory/createOpenApiTool.js +22 -0
- package/src/tool-factory/createOpenApiToolSync.js +22 -0
- package/src/tool-factory/createOpenApiTools.js +21 -0
- package/src/tool-factory/createOpenApiToolsSync.js +20 -0
- package/src/tool-factory/index.js +5 -0
- package/src/tool-factory/listOperations.js +23 -0
- package/src/tool-factory.js +1 -0
- package/src/types.js +20 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Shared private helpers for OpenAPI tool factory
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { tool, zodSchema } from "ai";
|
|
5
|
+
import { Effect, Metric } from "effect";
|
|
6
|
+
import { nowMs } from "@smithers-orchestrator/scheduler/nowMs";
|
|
7
|
+
import { openApiToolCallsTotal, openApiToolCallErrorsTotal, openApiToolDuration, } from "../metrics.js";
|
|
8
|
+
import { buildOperationSchema } from "../schema-converter.js";
|
|
9
|
+
import { extractOperations } from "../spec-parser.js";
|
|
10
|
+
/** @typedef {import("../OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
11
|
+
/** @typedef {import("../OpenApiTool.ts").OpenApiTool} OpenApiTool */
|
|
12
|
+
/** @typedef {import("../OpenApiToolsOptions.ts").OpenApiToolsOptions} OpenApiToolsOptions */
|
|
13
|
+
/** @typedef {import("../ParsedOperation.ts").ParsedOperation} ParsedOperation */
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// HTTP execution
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* @param {OpenApiToolsOptions} options
|
|
20
|
+
* @returns {Record<string, string>}
|
|
21
|
+
*/
|
|
22
|
+
export function buildAuthHeaders(options) {
|
|
23
|
+
const headers = {};
|
|
24
|
+
if (options.auth) {
|
|
25
|
+
switch (options.auth.type) {
|
|
26
|
+
case "bearer":
|
|
27
|
+
headers["Authorization"] = `Bearer ${options.auth.token}`;
|
|
28
|
+
break;
|
|
29
|
+
case "basic": {
|
|
30
|
+
const encoded = btoa(`${options.auth.username}:${options.auth.password}`);
|
|
31
|
+
headers["Authorization"] = `Basic ${encoded}`;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case "apiKey":
|
|
35
|
+
if (options.auth.in === "header") {
|
|
36
|
+
headers[options.auth.name] = options.auth.value;
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (options.headers) {
|
|
42
|
+
Object.assign(headers, options.headers);
|
|
43
|
+
}
|
|
44
|
+
return headers;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} baseUrl
|
|
48
|
+
* @param {string} path
|
|
49
|
+
* @param {Record<string, string>} pathParams
|
|
50
|
+
* @param {Record<string, string>} queryParams
|
|
51
|
+
* @param {OpenApiToolsOptions} options
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
export function buildUrl(baseUrl, path, pathParams, queryParams, options) {
|
|
55
|
+
// Substitute path parameters
|
|
56
|
+
let url = path;
|
|
57
|
+
for (const [key, value] of Object.entries(pathParams)) {
|
|
58
|
+
url = url.replace(`{${key}}`, encodeURIComponent(value));
|
|
59
|
+
}
|
|
60
|
+
const fullUrl = new URL(url, baseUrl);
|
|
61
|
+
// Add query parameters
|
|
62
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
63
|
+
fullUrl.searchParams.set(key, value);
|
|
64
|
+
}
|
|
65
|
+
// Add API key to query if configured
|
|
66
|
+
if (options.auth?.type === "apiKey" && options.auth.in === "query") {
|
|
67
|
+
fullUrl.searchParams.set(options.auth.name, options.auth.value);
|
|
68
|
+
}
|
|
69
|
+
return fullUrl.toString();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @param {ParsedOperation} operation
|
|
73
|
+
* @param {Record<string, unknown>} args
|
|
74
|
+
* @param {string} baseUrl
|
|
75
|
+
* @param {OpenApiToolsOptions} options
|
|
76
|
+
* @returns {Promise<unknown>}
|
|
77
|
+
*/
|
|
78
|
+
export async function executeRequest(operation, args, baseUrl, options) {
|
|
79
|
+
/** @type {Record<string, string>} */
|
|
80
|
+
const pathParams = {};
|
|
81
|
+
/** @type {Record<string, string>} */
|
|
82
|
+
const queryParams = {};
|
|
83
|
+
/** @type {Record<string, string>} */
|
|
84
|
+
const headerParams = {};
|
|
85
|
+
// Sort parameters into buckets
|
|
86
|
+
for (const param of operation.parameters) {
|
|
87
|
+
const value = args[param.name];
|
|
88
|
+
if (value === undefined)
|
|
89
|
+
continue;
|
|
90
|
+
const strValue = String(value);
|
|
91
|
+
switch (param.in) {
|
|
92
|
+
case "path":
|
|
93
|
+
pathParams[param.name] = strValue;
|
|
94
|
+
break;
|
|
95
|
+
case "query":
|
|
96
|
+
queryParams[param.name] = strValue;
|
|
97
|
+
break;
|
|
98
|
+
case "header":
|
|
99
|
+
headerParams[param.name] = strValue;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const url = buildUrl(baseUrl, operation.path, pathParams, queryParams, options);
|
|
104
|
+
/** @type {Record<string, string>} */
|
|
105
|
+
const headers = {
|
|
106
|
+
...buildAuthHeaders(options),
|
|
107
|
+
...headerParams,
|
|
108
|
+
};
|
|
109
|
+
/** @type {RequestInit} */
|
|
110
|
+
const fetchInit = {
|
|
111
|
+
method: operation.method.toUpperCase(),
|
|
112
|
+
headers,
|
|
113
|
+
};
|
|
114
|
+
// Request body
|
|
115
|
+
if (args.body !== undefined) {
|
|
116
|
+
headers["Content-Type"] = "application/json";
|
|
117
|
+
fetchInit.headers = headers;
|
|
118
|
+
fetchInit.body = JSON.stringify(args.body);
|
|
119
|
+
}
|
|
120
|
+
const response = await fetch(url, fetchInit);
|
|
121
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
122
|
+
if (contentType.includes("application/json")) {
|
|
123
|
+
return response.json();
|
|
124
|
+
}
|
|
125
|
+
return response.text();
|
|
126
|
+
}
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Effect-wrapped execution with metrics
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
/**
|
|
131
|
+
* @param {ParsedOperation} operation
|
|
132
|
+
* @param {Record<string, unknown>} args
|
|
133
|
+
* @param {string} baseUrl
|
|
134
|
+
* @param {OpenApiToolsOptions} options
|
|
135
|
+
* @returns {Effect.Effect<unknown, unknown, never>}
|
|
136
|
+
*/
|
|
137
|
+
export function executeToolEffect(operation, args, baseUrl, options) {
|
|
138
|
+
const started = nowMs();
|
|
139
|
+
return Effect.gen(function* () {
|
|
140
|
+
yield* Metric.increment(openApiToolCallsTotal);
|
|
141
|
+
const result = yield* Effect.tryPromise({
|
|
142
|
+
try: () => executeRequest(operation, args, baseUrl, options),
|
|
143
|
+
catch: (err) => err,
|
|
144
|
+
});
|
|
145
|
+
const durationMs = nowMs() - started;
|
|
146
|
+
yield* Metric.update(openApiToolDuration, durationMs);
|
|
147
|
+
return result;
|
|
148
|
+
}).pipe(Effect.tapError(() => Metric.increment(openApiToolCallErrorsTotal)), Effect.annotateLogs({
|
|
149
|
+
toolName: `openapi:${operation.operationId}`,
|
|
150
|
+
method: operation.method,
|
|
151
|
+
path: operation.path,
|
|
152
|
+
}), Effect.withLogSpan(`openapi:${operation.operationId}`));
|
|
153
|
+
}
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
// Tool creation
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
/**
|
|
158
|
+
* @param {ParsedOperation} operation
|
|
159
|
+
* @param {OpenApiSpec} spec
|
|
160
|
+
* @param {string} baseUrl
|
|
161
|
+
* @param {OpenApiToolsOptions} options
|
|
162
|
+
* @returns {{ name: string; tool: OpenApiTool }}
|
|
163
|
+
*/
|
|
164
|
+
export function createToolFromOperation(operation, spec, baseUrl, options) {
|
|
165
|
+
const inputSchema = buildOperationSchema(operation.parameters, operation.requestBody, spec);
|
|
166
|
+
const description = operation.summary || operation.description || operation.operationId;
|
|
167
|
+
const prefix = options.namePrefix ?? "";
|
|
168
|
+
return {
|
|
169
|
+
name: `${prefix}${operation.operationId}`,
|
|
170
|
+
tool: tool({
|
|
171
|
+
description,
|
|
172
|
+
inputSchema: zodSchema(inputSchema),
|
|
173
|
+
execute: async (args) => {
|
|
174
|
+
try {
|
|
175
|
+
return await Effect.runPromise(executeToolEffect(operation, /** @type {Record<string, unknown>} */ (args), baseUrl, options));
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
// Return error info as tool result instead of throwing
|
|
179
|
+
const e = /** @type {{ message?: string }} */ (error);
|
|
180
|
+
return {
|
|
181
|
+
error: true,
|
|
182
|
+
message: e?.message ?? String(error),
|
|
183
|
+
status: "failed",
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
}),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* @param {OpenApiSpec} spec
|
|
192
|
+
* @param {OpenApiToolsOptions} options
|
|
193
|
+
* @returns {string}
|
|
194
|
+
*/
|
|
195
|
+
export function resolveBaseUrl(spec, options) {
|
|
196
|
+
if (options.baseUrl)
|
|
197
|
+
return options.baseUrl;
|
|
198
|
+
if (spec.servers && spec.servers.length > 0)
|
|
199
|
+
return spec.servers[0].url;
|
|
200
|
+
return "http://localhost";
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* @param {OpenApiSpec} spec
|
|
204
|
+
* @param {OpenApiToolsOptions} options
|
|
205
|
+
* @returns {Record<string, OpenApiTool>}
|
|
206
|
+
*/
|
|
207
|
+
export function createOpenApiToolsFromSpec(spec, options) {
|
|
208
|
+
const operations = extractOperations(spec);
|
|
209
|
+
const baseUrl = resolveBaseUrl(spec, options);
|
|
210
|
+
/** @type {Record<string, OpenApiTool>} */
|
|
211
|
+
const tools = {};
|
|
212
|
+
for (const op of operations) {
|
|
213
|
+
// Apply include/exclude filters
|
|
214
|
+
if (options.include && !options.include.includes(op.operationId))
|
|
215
|
+
continue;
|
|
216
|
+
if (options.exclude && options.exclude.includes(op.operationId))
|
|
217
|
+
continue;
|
|
218
|
+
const { name, tool: t } = createToolFromOperation(op, spec, baseUrl, options);
|
|
219
|
+
tools[name] = t;
|
|
220
|
+
}
|
|
221
|
+
return tools;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* @param {OpenApiSpec} spec
|
|
225
|
+
* @param {string} operationId
|
|
226
|
+
* @param {OpenApiToolsOptions} options
|
|
227
|
+
* @returns {OpenApiTool}
|
|
228
|
+
*/
|
|
229
|
+
export function createOpenApiToolFromSpec(spec, operationId, options) {
|
|
230
|
+
const operations = extractOperations(spec);
|
|
231
|
+
const op = operations.find((o) => o.operationId === operationId);
|
|
232
|
+
if (!op) {
|
|
233
|
+
throw new Error(`Operation "${operationId}" not found in spec. Available: ${operations.map((o) => o.operationId).join(", ")}`);
|
|
234
|
+
}
|
|
235
|
+
const baseUrl = resolveBaseUrl(spec, options);
|
|
236
|
+
return createToolFromOperation(op, spec, baseUrl, options).tool;
|
|
237
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// createOpenApiTool — async single tool creation from OpenAPI spec
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
import { loadSpecEffect } from "../spec-parser.js";
|
|
6
|
+
import { createOpenApiToolFromSpec } from "./_helpers.js";
|
|
7
|
+
|
|
8
|
+
/** @typedef {import("../OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
9
|
+
/** @typedef {import("../OpenApiToolsOptions.ts").OpenApiToolsOptions} OpenApiToolsOptions */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a single AI SDK tool from an OpenAPI spec by operationId.
|
|
13
|
+
*
|
|
14
|
+
* @param {string | OpenApiSpec} input - OpenAPI spec as JSON object, file path, URL, or raw text
|
|
15
|
+
* @param {string} operationId - The operationId of the operation to create a tool for
|
|
16
|
+
* @param {OpenApiToolsOptions} [options] - Configuration for auth, base URL, etc.
|
|
17
|
+
* @returns {Promise<any>} A single AI SDK tool
|
|
18
|
+
*/
|
|
19
|
+
export async function createOpenApiTool(input, operationId, options = {}) {
|
|
20
|
+
const spec = await Effect.runPromise(loadSpecEffect(input));
|
|
21
|
+
return createOpenApiToolFromSpec(spec, operationId, options);
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// createOpenApiToolSync — synchronous single tool creation from OpenAPI spec
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { loadSpecSync } from "../spec-parser.js";
|
|
5
|
+
import { createOpenApiToolFromSpec } from "./_helpers.js";
|
|
6
|
+
|
|
7
|
+
/** @typedef {import("../OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
8
|
+
/** @typedef {import("../OpenApiTool.ts").OpenApiTool} OpenApiTool */
|
|
9
|
+
/** @typedef {import("../OpenApiToolsOptions.ts").OpenApiToolsOptions} OpenApiToolsOptions */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Synchronous version — only works with specs that are objects or local files.
|
|
13
|
+
*
|
|
14
|
+
* @param {string | OpenApiSpec} input
|
|
15
|
+
* @param {string} operationId
|
|
16
|
+
* @param {OpenApiToolsOptions} [options]
|
|
17
|
+
* @returns {OpenApiTool}
|
|
18
|
+
*/
|
|
19
|
+
export function createOpenApiToolSync(input, operationId, options = {}) {
|
|
20
|
+
const spec = loadSpecSync(input);
|
|
21
|
+
return createOpenApiToolFromSpec(spec, operationId, options);
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// createOpenApiTools — async tool creation from OpenAPI spec
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
import { loadSpecEffect } from "../spec-parser.js";
|
|
6
|
+
import { createOpenApiToolsFromSpec } from "./_helpers.js";
|
|
7
|
+
|
|
8
|
+
/** @typedef {import("../OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
9
|
+
/** @typedef {import("../OpenApiToolsOptions.ts").OpenApiToolsOptions} OpenApiToolsOptions */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create AI SDK tools from all operations in an OpenAPI spec.
|
|
13
|
+
*
|
|
14
|
+
* @param {string | OpenApiSpec} input - OpenAPI spec as JSON object, file path, URL, or raw text
|
|
15
|
+
* @param {OpenApiToolsOptions} [options] - Configuration for auth, filtering, base URL, etc.
|
|
16
|
+
* @returns {Promise<Record<string, any>>} Record of operationId → AI SDK tool
|
|
17
|
+
*/
|
|
18
|
+
export async function createOpenApiTools(input, options = {}) {
|
|
19
|
+
const spec = await Effect.runPromise(loadSpecEffect(input));
|
|
20
|
+
return createOpenApiToolsFromSpec(spec, options);
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// createOpenApiToolsSync — synchronous tool creation from OpenAPI spec
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { loadSpecSync } from "../spec-parser.js";
|
|
5
|
+
import { createOpenApiToolsFromSpec } from "./_helpers.js";
|
|
6
|
+
|
|
7
|
+
/** @typedef {import("../OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
8
|
+
/** @typedef {import("../OpenApiToolsOptions.ts").OpenApiToolsOptions} OpenApiToolsOptions */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Synchronous version — only works with specs that are objects or local files.
|
|
12
|
+
*
|
|
13
|
+
* @param {string | OpenApiSpec} input
|
|
14
|
+
* @param {OpenApiToolsOptions} [options]
|
|
15
|
+
* @returns {Record<string, any>}
|
|
16
|
+
*/
|
|
17
|
+
export function createOpenApiToolsSync(input, options = {}) {
|
|
18
|
+
const spec = loadSpecSync(input);
|
|
19
|
+
return createOpenApiToolsFromSpec(spec, options);
|
|
20
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createOpenApiTools } from "./createOpenApiTools.js";
|
|
2
|
+
export { createOpenApiToolsSync } from "./createOpenApiToolsSync.js";
|
|
3
|
+
export { createOpenApiTool } from "./createOpenApiTool.js";
|
|
4
|
+
export { createOpenApiToolSync } from "./createOpenApiToolSync.js";
|
|
5
|
+
export { listOperations } from "./listOperations.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// listOperations — list all operations from an OpenAPI spec
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
import { loadSpecSync } from "../spec-parser.js";
|
|
5
|
+
import { extractOperations } from "../spec-parser.js";
|
|
6
|
+
|
|
7
|
+
/** @typedef {import("../OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* List all operations from a spec (for CLI preview).
|
|
11
|
+
*
|
|
12
|
+
* @param {string | OpenApiSpec} input
|
|
13
|
+
* @returns {Array<{ operationId: string; method: string; path: string; summary: string }>}
|
|
14
|
+
*/
|
|
15
|
+
export function listOperations(input) {
|
|
16
|
+
const spec = loadSpecSync(input);
|
|
17
|
+
return extractOperations(spec).map((op) => ({
|
|
18
|
+
operationId: op.operationId,
|
|
19
|
+
method: op.method.toUpperCase(),
|
|
20
|
+
path: op.path,
|
|
21
|
+
summary: op.summary,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createOpenApiTools, createOpenApiToolsSync, createOpenApiTool, createOpenApiToolSync, listOperations, } from "./tool-factory/index.js";
|
package/src/types.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// @smithers-type-exports-begin
|
|
2
|
+
/** @typedef {import("./HttpMethod.ts").HttpMethod} HttpMethod */
|
|
3
|
+
/** @typedef {import("./MediaTypeObject.ts").MediaTypeObject} MediaTypeObject */
|
|
4
|
+
/** @typedef {import("./OpenApiAuth.ts").OpenApiAuth} OpenApiAuth */
|
|
5
|
+
/** @typedef {import("./OpenApiSpec.ts").OpenApiSpec} OpenApiSpec */
|
|
6
|
+
/** @typedef {import("./OpenApiToolsOptions.ts").OpenApiToolsOptions} OpenApiToolsOptions */
|
|
7
|
+
/** @typedef {import("./OperationObject.ts").OperationObject} OperationObject */
|
|
8
|
+
/** @typedef {import("./ParameterObject.ts").ParameterObject} ParameterObject */
|
|
9
|
+
/** @typedef {import("./ParsedOperation.ts").ParsedOperation} ParsedOperation */
|
|
10
|
+
/** @typedef {import("./PathItem.ts").PathItem} PathItem */
|
|
11
|
+
/** @typedef {import("./RefObject.ts").RefObject} RefObject */
|
|
12
|
+
/** @typedef {import("./RequestBodyObject.ts").RequestBodyObject} RequestBodyObject */
|
|
13
|
+
/** @typedef {import("./SchemaObject.ts").SchemaObject} SchemaObject */
|
|
14
|
+
// @smithers-type-exports-end
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// OpenAPI types — minimal subset of OpenAPI 3.0+ needed for tool generation
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/** @type {HttpMethod[]} */
|
|
20
|
+
export const HTTP_METHODS = ["get", "post", "put", "delete", "patch"];
|