@adhd/apigen-codegen-openapi 0.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.
- package/index.d.ts +3 -0
- package/index.js +1 -0
- package/index.mjs +77 -0
- package/lib/to-openapi.d.ts +94 -0
- package/package.json +10 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const __apigen_pkg = "@adhd/apigen-codegen-openapi";
|
|
2
|
+
export { toOpenApi } from './lib/to-openapi';
|
|
3
|
+
export type { OpenApiDocument, OpenApiPathItem, OpenApiOperation, OpenApiParameter, OpenApiRequestBody, OpenApiResponse, ToOpenApiOptions } from './lib/to-openapi';
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function h(e){return e.words.join("-")}function m(e){return e.words.map(y).join("")}function b(e){return e.words.join("_")}function j(e,r={}){var d,g;const t=[e.namespace,...e.path],s=e.safe?"GET":"POST",o=((g=(d=r.http)==null?void 0:d.verb)==null?void 0:g[e.id])??s,n="/"+t.map(c=>h(c)).join("/"),u=t.map(c=>b(c)).join("_"),a=t.map(c=>b(c)).slice(0,-1).join("."),l=m(t[t.length-2]??t[0]),p=m(t[t.length-1]),i=t.map(c=>h(c));return{http:{verb:o,route:n},mcp:{name:u},grpc:{package:a,service:l,method:p},cli:{path:i}}}function y(e){return e.length===0?e:e[0].toUpperCase()+e.slice(1)}function v(e,r={}){const t=r.title??"API",s=r.version??"0.0.0",o={};for(const n of e){const u=j(n),{verb:f,route:a}=u.http,l=f.toLowerCase(),p={operationId:n.id,summary:n.id,responses:{200:P(n.output)}};if(n.safe)p.parameters=S(n.input);else{const i=n.input;typeof i=="object"&&i!==null&&Object.keys(i).length>0&&(p.requestBody={required:!0,content:{"application/json":{schema:i}}})}o[a]===void 0&&(o[a]={}),o[a][l]=p}return{openapi:"3.1.0",info:{title:t,version:s},paths:o}}function P(e){return typeof e=="object"&&e!==null&&Object.keys(e).length>0?{description:"Success",content:{"application/json":{schema:e}}}:{description:"Success"}}function S(e){if(typeof e!="object"||e===null||typeof e.properties!="object"||e.properties===null)return[];const r=Array.isArray(e.required)?e.required:[],t=e.properties;return Object.entries(t).map(([s,o])=>({name:s,in:"query",required:r.includes(s),schema:o}))}const O="@adhd/apigen-codegen-openapi";exports.__apigen_pkg=O;exports.toOpenApi=v;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function g(e) {
|
|
2
|
+
return e.words.join("-");
|
|
3
|
+
}
|
|
4
|
+
function m(e) {
|
|
5
|
+
return e.words.map(y).join("");
|
|
6
|
+
}
|
|
7
|
+
function j(e) {
|
|
8
|
+
return e.words.join("_");
|
|
9
|
+
}
|
|
10
|
+
function b(e, r = {}) {
|
|
11
|
+
var d, h;
|
|
12
|
+
const t = [e.namespace, ...e.path], s = e.safe ? "GET" : "POST", o = ((h = (d = r.http) == null ? void 0 : d.verb) == null ? void 0 : h[e.id]) ?? s, n = "/" + t.map((c) => g(c)).join("/"), u = t.map((c) => j(c)).join("_"), a = t.map((c) => j(c)).slice(0, -1).join("."), l = m(t[t.length - 2] ?? t[0]), p = m(t[t.length - 1]), i = t.map((c) => g(c));
|
|
13
|
+
return {
|
|
14
|
+
http: { verb: o, route: n },
|
|
15
|
+
mcp: { name: u },
|
|
16
|
+
grpc: { package: a, service: l, method: p },
|
|
17
|
+
cli: { path: i }
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function y(e) {
|
|
21
|
+
return e.length === 0 ? e : e[0].toUpperCase() + e.slice(1);
|
|
22
|
+
}
|
|
23
|
+
function q(e, r = {}) {
|
|
24
|
+
const t = r.title ?? "API", s = r.version ?? "0.0.0", o = {};
|
|
25
|
+
for (const n of e) {
|
|
26
|
+
const u = b(n), { verb: f, route: a } = u.http, l = f.toLowerCase(), p = {
|
|
27
|
+
operationId: n.id,
|
|
28
|
+
summary: n.id,
|
|
29
|
+
responses: {
|
|
30
|
+
200: v(n.output)
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
if (n.safe)
|
|
34
|
+
p.parameters = P(n.input);
|
|
35
|
+
else {
|
|
36
|
+
const i = n.input;
|
|
37
|
+
typeof i == "object" && i !== null && Object.keys(i).length > 0 && (p.requestBody = {
|
|
38
|
+
required: !0,
|
|
39
|
+
content: {
|
|
40
|
+
"application/json": {
|
|
41
|
+
schema: i
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
o[a] === void 0 && (o[a] = {}), o[a][l] = p;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
openapi: "3.1.0",
|
|
50
|
+
info: { title: t, version: s },
|
|
51
|
+
paths: o
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function v(e) {
|
|
55
|
+
return typeof e == "object" && e !== null && Object.keys(e).length > 0 ? {
|
|
56
|
+
description: "Success",
|
|
57
|
+
content: {
|
|
58
|
+
"application/json": { schema: e }
|
|
59
|
+
}
|
|
60
|
+
} : { description: "Success" };
|
|
61
|
+
}
|
|
62
|
+
function P(e) {
|
|
63
|
+
if (typeof e != "object" || e === null || typeof e.properties != "object" || e.properties === null)
|
|
64
|
+
return [];
|
|
65
|
+
const r = Array.isArray(e.required) ? e.required : [], t = e.properties;
|
|
66
|
+
return Object.entries(t).map(([s, o]) => ({
|
|
67
|
+
name: s,
|
|
68
|
+
in: "query",
|
|
69
|
+
required: r.includes(s),
|
|
70
|
+
schema: o
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
const S = "@adhd/apigen-codegen-openapi";
|
|
74
|
+
export {
|
|
75
|
+
S as __apigen_pkg,
|
|
76
|
+
q as toOpenApi
|
|
77
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Operation, JSONSchema } from '@adhd/apigen-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An OpenAPI 3.1 document. The type is intentionally open (Record) because
|
|
5
|
+
* we cannot enumerate every valid 3.1 keyword here — downstream consumers can
|
|
6
|
+
* narrow as needed.
|
|
7
|
+
*/
|
|
8
|
+
export type OpenApiDocument = {
|
|
9
|
+
openapi: '3.1.0';
|
|
10
|
+
info: {
|
|
11
|
+
title: string;
|
|
12
|
+
version: string;
|
|
13
|
+
};
|
|
14
|
+
paths: Record<string, OpenApiPathItem>;
|
|
15
|
+
components?: {
|
|
16
|
+
schemas?: Record<string, JSONSchema>;
|
|
17
|
+
};
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
};
|
|
20
|
+
/** An OpenAPI path-item object (subset sufficient for apigen projection). */
|
|
21
|
+
export type OpenApiPathItem = {
|
|
22
|
+
[verb: string]: OpenApiOperation;
|
|
23
|
+
};
|
|
24
|
+
/** An OpenAPI operation object (subset). */
|
|
25
|
+
export type OpenApiOperation = {
|
|
26
|
+
operationId: string;
|
|
27
|
+
summary?: string;
|
|
28
|
+
parameters?: OpenApiParameter[];
|
|
29
|
+
requestBody?: OpenApiRequestBody;
|
|
30
|
+
responses: Record<string, OpenApiResponse>;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
};
|
|
33
|
+
/** An OpenAPI parameter object (subset). */
|
|
34
|
+
export type OpenApiParameter = {
|
|
35
|
+
name: string;
|
|
36
|
+
in: 'query' | 'header' | 'path' | 'cookie';
|
|
37
|
+
required?: boolean;
|
|
38
|
+
schema: JSONSchema;
|
|
39
|
+
};
|
|
40
|
+
/** An OpenAPI request-body object (subset). */
|
|
41
|
+
export type OpenApiRequestBody = {
|
|
42
|
+
required: boolean;
|
|
43
|
+
content: {
|
|
44
|
+
'application/json': {
|
|
45
|
+
schema: JSONSchema;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/** An OpenAPI response object (subset). */
|
|
50
|
+
export type OpenApiResponse = {
|
|
51
|
+
description: string;
|
|
52
|
+
content?: {
|
|
53
|
+
'application/json': {
|
|
54
|
+
schema: JSONSchema;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Options for {@link toOpenApi}.
|
|
60
|
+
*/
|
|
61
|
+
export interface ToOpenApiOptions {
|
|
62
|
+
/**
|
|
63
|
+
* The API title placed in `info.title`.
|
|
64
|
+
* @default 'API'
|
|
65
|
+
*/
|
|
66
|
+
title?: string;
|
|
67
|
+
/**
|
|
68
|
+
* The API version placed in `info.version`.
|
|
69
|
+
* @default '0.0.0'
|
|
70
|
+
*/
|
|
71
|
+
version?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Projects an array of {@link Operation}s to an OpenAPI 3.1 document.
|
|
75
|
+
*
|
|
76
|
+
* HTTP verb derivation (SPEC §5): `safe → GET`, `!safe → POST`.
|
|
77
|
+
* - **GET**: domain params appear as query-string `parameters`.
|
|
78
|
+
* - **POST**: domain params are wrapped in a `requestBody` (`application/json`).
|
|
79
|
+
*
|
|
80
|
+
* The `input` and `output` JSON-Schema fragments are passed through verbatim
|
|
81
|
+
* (OpenAPI 3.1 natively supports JSON Schema 2020-12).
|
|
82
|
+
*
|
|
83
|
+
* @param operations - The canonical operations array from the merged descriptor.
|
|
84
|
+
* @param opts - Optional document-level metadata (title, version).
|
|
85
|
+
* @returns A standards-conformant OpenAPI 3.1 document.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const doc = toOpenApi(descriptor.operations, { title: 'My API', version: '1.0.0' })
|
|
90
|
+
* // doc.openapi === '3.1.0'
|
|
91
|
+
* // doc.paths['/transform/humanize/humanize-bytes']['post'] → { operationId, … }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function toOpenApi(operations: Operation[], opts?: ToOpenApiOptions): OpenApiDocument;
|