@adhd/apigen-plugin-openapi 0.2.1 → 0.2.3
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/CHANGELOG.md +22 -0
- package/index.js +1 -1
- package/index.mjs +35 -34
- package/package.json +22 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 0.2.3 (2026-09-24)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for apigen-plugin-openapi to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
5
|
+
## 0.2.2 (2026-08-07)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### 🚀 Features
|
|
9
|
+
|
|
10
|
+
- **apigen:** generic batch/bulk fan-out operations (FEAT-APIGEN-BULK-OPS-001)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### 🩹 Fixes
|
|
14
|
+
|
|
15
|
+
- **apigen-cli:** restore 2768 files mass-deleted by 0117eb22 (BUG-APIGEN-052)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### ❤️ Thank You
|
|
19
|
+
|
|
20
|
+
- parity-harness-self-test
|
|
21
|
+
- pseudosky
|
|
22
|
+
|
|
1
23
|
## 0.2.1 (2026-07-28)
|
|
2
24
|
|
|
3
25
|
This was a version bump only for apigen-plugin-openapi to align it with other projects, there were no code changes.
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require("
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require("node:fs");const v=require("node:module");require("node:path");var c=typeof document<"u"?document.currentScript:null;function m(e){return{raw:e,words:e.split(/(?=[A-Z])|[-_]/).map(t=>t.toLowerCase()).filter(Boolean)}}function O(e,t,n={}){const o=e.split("/");if(o.length<2||o.some(f=>f.length===0))throw new Error(`syntheticOp: id "${e}" must be "<namespace>/<path...>" with non-empty segments`);const[r,...i]=o,l=r.replace(/^_+/,""),a=n.kind??"action",s={id:e,host:t.host,namespace:m(l),path:i.map(m),kind:a,async:n.async??!1,streaming:n.streaming??!1,safe:n.safe??a==="query",input:n.input??{},output:n.output??{},envelope:n.envelope??{},typeText:n.typeText??null};return n.hasCtx!==void 0&&(s.hasCtx=n.hasCtx),n.transports!==void 0&&(s.transports=n.transports),s}v.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:c&&c.tagName.toUpperCase()==="SCRIPT"&&c.src||new URL("index.js",document.baseURI).href);const q={"decimal.js":"Decimal"};function _(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Object.entries(q).map(([e,t])=>({pattern:new RegExp(`import\\(["'][^"']*${_(e)}[^"']*["']\\)\\.\\w+`,"g"),key:t}));v.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:c&&c.tagName.toUpperCase()==="SCRIPT"&&c.src||new URL("index.js",document.baseURI).href);const y=new Set(["string","number","boolean","integer"]);function R(e){if(typeof e!="object"||e===null)return!1;const t=e;if(t.$ref!==void 0||t.oneOf||t.anyOf||t.allOf)return!1;const{type:n}=t;return typeof n=="string"?y.has(n):Array.isArray(n)?n.every(o=>y.has(o)||o==="null"):Array.isArray(t.enum)&&t.enum.length>0?t.enum.every(o=>["string","number","boolean"].includes(typeof o)):!1}function A(e){if(!e||typeof e!="object")return!1;const t=e.properties;return t===void 0||typeof t!="object"||t===null?!1:Object.values(t).every(R)}const S={"decimal.js":"Decimal"};function C(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Object.entries(S).map(([e,t])=>({pattern:new RegExp(`import\\(["'][^"']*${C(e)}[^"']*["']\\)\\.\\w+`,"g"),key:t}));function h(e){return e.words.join("-")}function g(e){return e.words.map(T).join("")}function b(e){return e.words.join("_")}function P(e,t={}){var n,o;const r=[e.namespace,...e.path],i=e.safe||A(e.input)?"GET":"POST",l=((o=(n=t.http)==null?void 0:n.verb)==null?void 0:o[e.id])??i,a="/"+r.map(p=>h(p)).join("/"),s=r.map(p=>b(p)).join("_"),f=r.map(p=>b(p)).slice(0,-1).join("."),d=g(r[r.length-2]??r[0]),u=g(r[r.length-1]),w=r.map(p=>h(p));return{http:{verb:l,route:a},mcp:{name:s},grpc:{package:f,service:d,method:u},cli:{path:w}}}function T(e){return e.length===0?e:e[0].toUpperCase()+e.slice(1)}function x(e,t={}){const n=t.title??"API",o=t.version??"0.0.0",r={};for(const i of e){const l=P(i),{verb:a,route:s}=l.http,f=a.toLowerCase(),d={operationId:i.id,summary:i.id,responses:{200:I(i.output)}};if(a==="GET")d.parameters=U(i.input);else{const u=i.input;typeof u=="object"&&u!==null&&Object.keys(u).length>0&&(d.requestBody={required:!0,content:{"application/json":{schema:u}}})}r[s]===void 0&&(r[s]={}),r[s][f]=d}return{openapi:"3.1.0",info:{title:n,version:o},paths:r}}function I(e){return typeof e=="object"&&e!==null&&Object.keys(e).length>0?{description:"Success",content:{"application/json":{schema:e}}}:{description:"Success"}}function U(e){if(typeof e!="object"||e===null||typeof e.properties!="object"||e.properties===null)return[];const t=Array.isArray(e.required)?e.required:[],n=e.properties;return Object.entries(n).map(([o,r])=>({name:o,in:"query",required:t.includes(o),schema:r}))}function k(e,t={}){return[{...O("_meta/openapi",e,{kind:"query",safe:!0,output:{type:"object"},transports:["http"]}),handler:n=>x(e.operations,{title:t.title,version:t.version})}]}const j={id:"openapi",description:"Mount plugin: serves the OpenAPI 3.1 doc at GET /meta/openapi",language:"ts",optionsSchema:{type:"object",properties:{title:{type:"string",description:"OpenAPI info.title"},version:{type:"string",description:"OpenAPI info.version"}},additionalProperties:!1},capabilities:{mount:{operations(e,t){return k(e,t)}}}};exports.default=j;exports.openapiPlugin=j;
|
package/index.mjs
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import "ts-morph";
|
|
2
1
|
import "node:fs";
|
|
2
|
+
import { createRequire as b } from "node:module";
|
|
3
3
|
import "node:path";
|
|
4
|
-
import "ts-json-schema-generator";
|
|
5
4
|
function m(e) {
|
|
6
5
|
return {
|
|
7
6
|
raw: e,
|
|
8
7
|
words: e.split(/(?=[A-Z])|[-_]/).map((t) => t.toLowerCase()).filter(Boolean)
|
|
9
8
|
};
|
|
10
9
|
}
|
|
11
|
-
function
|
|
12
|
-
const
|
|
13
|
-
if (
|
|
10
|
+
function j(e, t, n = {}) {
|
|
11
|
+
const r = e.split("/");
|
|
12
|
+
if (r.length < 2 || r.some((l) => l.length === 0))
|
|
14
13
|
throw new Error(
|
|
15
14
|
`syntheticOp: id "${e}" must be "<namespace>/<path...>" with non-empty segments`
|
|
16
15
|
);
|
|
17
|
-
const [
|
|
16
|
+
const [o, ...i] = r, c = o.replace(/^_+/, ""), p = n.kind ?? "action", s = {
|
|
18
17
|
id: e,
|
|
19
18
|
host: t.host,
|
|
20
19
|
namespace: m(c),
|
|
@@ -30,13 +29,14 @@ function b(e, t, n = {}) {
|
|
|
30
29
|
};
|
|
31
30
|
return n.hasCtx !== void 0 && (s.hasCtx = n.hasCtx), n.transports !== void 0 && (s.transports = n.transports), s;
|
|
32
31
|
}
|
|
33
|
-
|
|
32
|
+
b(import.meta.url);
|
|
33
|
+
const O = {
|
|
34
34
|
"decimal.js": "Decimal"
|
|
35
35
|
};
|
|
36
|
-
function
|
|
36
|
+
function w(e) {
|
|
37
37
|
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
38
38
|
}
|
|
39
|
-
Object.entries(
|
|
39
|
+
Object.entries(O).map(([e, t]) => ({
|
|
40
40
|
// Matches: import("...{modSpec}...").<anyMemberName> (single or double quotes)
|
|
41
41
|
// The module specifier appears inside an absolute path, so we allow any
|
|
42
42
|
// characters between the quote and the specifier, and between the specifier
|
|
@@ -44,36 +44,37 @@ Object.entries(j).map(([e, t]) => ({
|
|
|
44
44
|
// …) is matched generically (`\w+`) rather than anchored to one spelling —
|
|
45
45
|
// see the doc comment above for why.
|
|
46
46
|
pattern: new RegExp(
|
|
47
|
-
`import\\(["'][^"']*${
|
|
47
|
+
`import\\(["'][^"']*${w(e)}[^"']*["']\\)\\.\\w+`,
|
|
48
48
|
"g"
|
|
49
49
|
),
|
|
50
50
|
key: t
|
|
51
51
|
}));
|
|
52
|
+
b(import.meta.url);
|
|
52
53
|
const d = /* @__PURE__ */ new Set(["string", "number", "boolean", "integer"]);
|
|
53
|
-
function
|
|
54
|
+
function A(e) {
|
|
54
55
|
if (typeof e != "object" || e === null)
|
|
55
56
|
return !1;
|
|
56
57
|
const t = e;
|
|
57
58
|
if (t.$ref !== void 0 || t.oneOf || t.anyOf || t.allOf)
|
|
58
59
|
return !1;
|
|
59
60
|
const { type: n } = t;
|
|
60
|
-
return typeof n == "string" ? d.has(n) : Array.isArray(n) ? n.every((
|
|
61
|
+
return typeof n == "string" ? d.has(n) : Array.isArray(n) ? n.every((r) => d.has(r) || r === "null") : Array.isArray(t.enum) && t.enum.length > 0 ? t.enum.every((r) => ["string", "number", "boolean"].includes(typeof r)) : !1;
|
|
61
62
|
}
|
|
62
|
-
function
|
|
63
|
+
function q(e) {
|
|
63
64
|
if (!e || typeof e != "object")
|
|
64
65
|
return !1;
|
|
65
66
|
const t = e.properties;
|
|
66
67
|
return t === void 0 || typeof t != "object" || t === null ? !1 : Object.values(t).every(
|
|
67
|
-
|
|
68
|
+
A
|
|
68
69
|
);
|
|
69
70
|
}
|
|
70
|
-
const
|
|
71
|
+
const k = {
|
|
71
72
|
"decimal.js": "Decimal"
|
|
72
73
|
};
|
|
73
74
|
function x(e) {
|
|
74
75
|
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
75
76
|
}
|
|
76
|
-
Object.entries(
|
|
77
|
+
Object.entries(k).map(([e, t]) => ({
|
|
77
78
|
// Matches: import("...{modSpec}...").<anyMemberName> (single or double quotes)
|
|
78
79
|
// The module specifier appears inside an absolute path, so we allow any
|
|
79
80
|
// characters between the quote and the specifier, and between the specifier
|
|
@@ -95,9 +96,9 @@ function h(e) {
|
|
|
95
96
|
function g(e) {
|
|
96
97
|
return e.words.join("_");
|
|
97
98
|
}
|
|
98
|
-
function
|
|
99
|
-
var n,
|
|
100
|
-
const
|
|
99
|
+
function _(e, t = {}) {
|
|
100
|
+
var n, r;
|
|
101
|
+
const o = [e.namespace, ...e.path], i = e.safe || q(e.input) ? "GET" : "POST", c = ((r = (n = t.http) == null ? void 0 : n.verb) == null ? void 0 : r[e.id]) ?? i, p = "/" + o.map((a) => y(a)).join("/"), s = o.map((a) => g(a)).join("_"), l = o.map((a) => g(a)).slice(0, -1).join("."), f = h(o[o.length - 2] ?? o[0]), u = h(o[o.length - 1]), v = o.map((a) => y(a));
|
|
101
102
|
return {
|
|
102
103
|
http: { verb: c, route: p },
|
|
103
104
|
mcp: { name: s },
|
|
@@ -109,9 +110,9 @@ function $(e) {
|
|
|
109
110
|
return e.length === 0 ? e : e[0].toUpperCase() + e.slice(1);
|
|
110
111
|
}
|
|
111
112
|
function E(e, t = {}) {
|
|
112
|
-
const n = t.title ?? "API",
|
|
113
|
+
const n = t.title ?? "API", r = t.version ?? "0.0.0", o = {};
|
|
113
114
|
for (const i of e) {
|
|
114
|
-
const c =
|
|
115
|
+
const c = _(i), { verb: p, route: s } = c.http, l = p.toLowerCase(), f = {
|
|
115
116
|
operationId: i.id,
|
|
116
117
|
summary: i.id,
|
|
117
118
|
responses: {
|
|
@@ -131,12 +132,12 @@ function E(e, t = {}) {
|
|
|
131
132
|
}
|
|
132
133
|
});
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
o[s] === void 0 && (o[s] = {}), o[s][l] = f;
|
|
135
136
|
}
|
|
136
137
|
return {
|
|
137
138
|
openapi: "3.1.0",
|
|
138
|
-
info: { title: n, version:
|
|
139
|
-
paths:
|
|
139
|
+
info: { title: n, version: r },
|
|
140
|
+
paths: o
|
|
140
141
|
};
|
|
141
142
|
}
|
|
142
143
|
function P(e) {
|
|
@@ -151,17 +152,17 @@ function C(e) {
|
|
|
151
152
|
if (typeof e != "object" || e === null || typeof e.properties != "object" || e.properties === null)
|
|
152
153
|
return [];
|
|
153
154
|
const t = Array.isArray(e.required) ? e.required : [], n = e.properties;
|
|
154
|
-
return Object.entries(n).map(([
|
|
155
|
-
name:
|
|
155
|
+
return Object.entries(n).map(([r, o]) => ({
|
|
156
|
+
name: r,
|
|
156
157
|
in: "query",
|
|
157
|
-
required: t.includes(
|
|
158
|
-
schema:
|
|
158
|
+
required: t.includes(r),
|
|
159
|
+
schema: o
|
|
159
160
|
}));
|
|
160
161
|
}
|
|
161
|
-
function
|
|
162
|
+
function S(e, t = {}) {
|
|
162
163
|
return [
|
|
163
164
|
{
|
|
164
|
-
...
|
|
165
|
+
...j("_meta/openapi", e, {
|
|
165
166
|
// query + safe → GET /meta/openapi (SPEC §5)
|
|
166
167
|
kind: "query",
|
|
167
168
|
safe: !0,
|
|
@@ -179,7 +180,7 @@ function I(e, t = {}) {
|
|
|
179
180
|
}
|
|
180
181
|
];
|
|
181
182
|
}
|
|
182
|
-
const
|
|
183
|
+
const G = {
|
|
183
184
|
id: "openapi",
|
|
184
185
|
description: "Mount plugin: serves the OpenAPI 3.1 doc at GET /meta/openapi",
|
|
185
186
|
language: "ts",
|
|
@@ -194,7 +195,7 @@ const B = {
|
|
|
194
195
|
capabilities: {
|
|
195
196
|
mount: {
|
|
196
197
|
operations(e, t) {
|
|
197
|
-
return
|
|
198
|
+
return S(
|
|
198
199
|
e,
|
|
199
200
|
t
|
|
200
201
|
);
|
|
@@ -203,6 +204,6 @@ const B = {
|
|
|
203
204
|
}
|
|
204
205
|
};
|
|
205
206
|
export {
|
|
206
|
-
|
|
207
|
-
|
|
207
|
+
G as default,
|
|
208
|
+
G as openapiPlugin
|
|
208
209
|
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhd/apigen-plugin-openapi",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"main": "./index.js",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@adhd/apigen-core-client": "^0.
|
|
7
|
-
"@adhd/apigen-codegen-openapi": "^0.2.
|
|
6
|
+
"@adhd/apigen-core-client": "^0.3.1",
|
|
7
|
+
"@adhd/apigen-codegen-openapi": "^0.2.3"
|
|
8
8
|
},
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
12
|
"module": "./index.mjs",
|
|
13
|
-
"types": "./index.d.ts"
|
|
13
|
+
"types": "./index.d.ts",
|
|
14
|
+
"description": "apigen plugin that live-mounts TypeScript as an OpenAPI document",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"openapi",
|
|
17
|
+
"apigen",
|
|
18
|
+
"typescript",
|
|
19
|
+
"plugin",
|
|
20
|
+
"codegen"
|
|
21
|
+
],
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/PseudoSky/adhd.git",
|
|
26
|
+
"directory": "packages/apigen/apigen-plugin-openapi"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/PseudoSky/adhd/tree/main/packages/apigen/apigen-plugin-openapi#readme",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/PseudoSky/adhd/issues"
|
|
31
|
+
}
|
|
14
32
|
}
|