@adhd/apigen-plugin-openapi 0.2.1 → 0.2.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/CHANGELOG.md +18 -0
- package/index.js +1 -1
- package/index.mjs +37 -37
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 0.2.2 (2026-08-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### 🚀 Features
|
|
5
|
+
|
|
6
|
+
- **apigen:** generic batch/bulk fan-out operations (FEAT-APIGEN-BULK-OPS-001)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### 🩹 Fixes
|
|
10
|
+
|
|
11
|
+
- **apigen-cli:** restore 2768 files mass-deleted by 0117eb22 (BUG-APIGEN-052)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### ❤️ Thank You
|
|
15
|
+
|
|
16
|
+
- parity-harness-self-test
|
|
17
|
+
- pseudosky
|
|
18
|
+
|
|
1
19
|
## 0.2.1 (2026-07-28)
|
|
2
20
|
|
|
3
21
|
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("ts-morph");require("node:fs");require("node:path");require("ts-json-schema-generator");function m(e){return{raw:e,words:e.split(/(?=[A-Z])|[-_]/).map(t=>t.toLowerCase()).filter(Boolean)}}function j(e,t,n={}){const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require("ts-morph");require("node:fs");require("node:path");require("ts-json-schema-generator");function m(e){return{raw:e,words:e.split(/(?=[A-Z])|[-_]/).map(t=>t.toLowerCase()).filter(Boolean)}}function j(e,t,n={}){const r=e.split("/");if(r.length<2||r.some(l=>l.length===0))throw new Error(`syntheticOp: id "${e}" must be "<namespace>/<path...>" with non-empty segments`);const[o,...i]=r,c=o.replace(/^_+/,""),p=n.kind??"action",s={id:e,host:t.host,namespace:m(c),path:i.map(m),kind:p,async:n.async??!1,streaming:n.streaming??!1,safe:n.safe??p==="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}const O={"decimal.js":"Decimal"};function w(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Object.entries(O).map(([e,t])=>({pattern:new RegExp(`import\\(["'][^"']*${w(e)}[^"']*["']\\)\\.\\w+`,"g"),key:t}));const d=new Set(["string","number","boolean","integer"]);function q(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"?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}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(q)}const P={"decimal.js":"Decimal"};function k(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Object.entries(P).map(([e,t])=>({pattern:new RegExp(`import\\(["'][^"']*${k(e)}[^"']*["']\\)\\.\\w+`,"g"),key:t}));function y(e){return e.words.join("-")}function h(e){return e.words.map(_).join("")}function g(e){return e.words.join("_")}function S(e,t={}){var n,r;const o=[e.namespace,...e.path],i=e.safe||A(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));return{http:{verb:c,route:p},mcp:{name:s},grpc:{package:l,service:f,method:u},cli:{path:v}}}function _(e){return e.length===0?e:e[0].toUpperCase()+e.slice(1)}function $(e,t={}){const n=t.title??"API",r=t.version??"0.0.0",o={};for(const i of e){const c=S(i),{verb:p,route:s}=c.http,l=p.toLowerCase(),f={operationId:i.id,summary:i.id,responses:{200:x(i.output)}};if(p==="GET")f.parameters=E(i.input);else{const u=i.input;typeof u=="object"&&u!==null&&Object.keys(u).length>0&&(f.requestBody={required:!0,content:{"application/json":{schema:u}}})}o[s]===void 0&&(o[s]={}),o[s][l]=f}return{openapi:"3.1.0",info:{title:n,version:r},paths:o}}function x(e){return typeof e=="object"&&e!==null&&Object.keys(e).length>0?{description:"Success",content:{"application/json":{schema:e}}}:{description:"Success"}}function E(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(([r,o])=>({name:r,in:"query",required:t.includes(r),schema:o}))}function T(e,t={}){return[{...j("_meta/openapi",e,{kind:"query",safe:!0,output:{type:"object"},transports:["http"]}),handler:n=>$(e.operations,{title:t.title,version:t.version})}]}const b={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 T(e,t)}}}};exports.default=b;exports.openapiPlugin=b;
|
package/index.mjs
CHANGED
|
@@ -8,17 +8,17 @@ function m(e) {
|
|
|
8
8
|
words: e.split(/(?=[A-Z])|[-_]/).map((t) => t.toLowerCase()).filter(Boolean)
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
function
|
|
12
|
-
const
|
|
13
|
-
if (
|
|
11
|
+
function j(e, t, n = {}) {
|
|
12
|
+
const i = e.split("/");
|
|
13
|
+
if (i.length < 2 || i.some((l) => l.length === 0))
|
|
14
14
|
throw new Error(
|
|
15
15
|
`syntheticOp: id "${e}" must be "<namespace>/<path...>" with non-empty segments`
|
|
16
16
|
);
|
|
17
|
-
const [
|
|
17
|
+
const [o, ...r] = i, c = o.replace(/^_+/, ""), p = n.kind ?? "action", s = {
|
|
18
18
|
id: e,
|
|
19
19
|
host: t.host,
|
|
20
20
|
namespace: m(c),
|
|
21
|
-
path:
|
|
21
|
+
path: r.map(m),
|
|
22
22
|
kind: p,
|
|
23
23
|
async: n.async ?? !1,
|
|
24
24
|
streaming: n.streaming ?? !1,
|
|
@@ -30,13 +30,13 @@ function b(e, t, n = {}) {
|
|
|
30
30
|
};
|
|
31
31
|
return n.hasCtx !== void 0 && (s.hasCtx = n.hasCtx), n.transports !== void 0 && (s.transports = n.transports), s;
|
|
32
32
|
}
|
|
33
|
-
const
|
|
33
|
+
const v = {
|
|
34
34
|
"decimal.js": "Decimal"
|
|
35
35
|
};
|
|
36
36
|
function O(e) {
|
|
37
37
|
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
38
38
|
}
|
|
39
|
-
Object.entries(
|
|
39
|
+
Object.entries(v).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
|
|
@@ -57,7 +57,7 @@ function w(e) {
|
|
|
57
57
|
if (t.$ref !== void 0 || t.oneOf || t.anyOf || t.allOf)
|
|
58
58
|
return !1;
|
|
59
59
|
const { type: n } = t;
|
|
60
|
-
return typeof n == "string" ? d.has(n) : Array.isArray(n) ? n.every((
|
|
60
|
+
return typeof n == "string" ? d.has(n) : Array.isArray(n) ? n.every((i) => d.has(i) || i === "null") : Array.isArray(t.enum) && t.enum.length > 0 ? t.enum.every((i) => ["string", "number", "boolean"].includes(typeof i)) : !1;
|
|
61
61
|
}
|
|
62
62
|
function A(e) {
|
|
63
63
|
if (!e || typeof e != "object")
|
|
@@ -70,7 +70,7 @@ function A(e) {
|
|
|
70
70
|
const q = {
|
|
71
71
|
"decimal.js": "Decimal"
|
|
72
72
|
};
|
|
73
|
-
function
|
|
73
|
+
function k(e) {
|
|
74
74
|
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
75
75
|
}
|
|
76
76
|
Object.entries(q).map(([e, t]) => ({
|
|
@@ -81,7 +81,7 @@ Object.entries(q).map(([e, t]) => ({
|
|
|
81
81
|
// …) is matched generically (`\w+`) rather than anchored to one spelling —
|
|
82
82
|
// see the doc comment above for why.
|
|
83
83
|
pattern: new RegExp(
|
|
84
|
-
`import\\(["'][^"']*${
|
|
84
|
+
`import\\(["'][^"']*${k(e)}[^"']*["']\\)\\.\\w+`,
|
|
85
85
|
"g"
|
|
86
86
|
),
|
|
87
87
|
key: t
|
|
@@ -90,38 +90,38 @@ function y(e) {
|
|
|
90
90
|
return e.words.join("-");
|
|
91
91
|
}
|
|
92
92
|
function h(e) {
|
|
93
|
-
return e.words.map(
|
|
93
|
+
return e.words.map(P).join("");
|
|
94
94
|
}
|
|
95
95
|
function g(e) {
|
|
96
96
|
return e.words.join("_");
|
|
97
97
|
}
|
|
98
|
-
function
|
|
99
|
-
var n,
|
|
100
|
-
const
|
|
98
|
+
function x(e, t = {}) {
|
|
99
|
+
var n, i;
|
|
100
|
+
const o = [e.namespace, ...e.path], r = e.safe || A(e.input) ? "GET" : "POST", c = ((i = (n = t.http) == null ? void 0 : n.verb) == null ? void 0 : i[e.id]) ?? r, 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]), b = o.map((a) => y(a));
|
|
101
101
|
return {
|
|
102
102
|
http: { verb: c, route: p },
|
|
103
103
|
mcp: { name: s },
|
|
104
104
|
grpc: { package: l, service: f, method: u },
|
|
105
|
-
cli: { path:
|
|
105
|
+
cli: { path: b }
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
-
function
|
|
108
|
+
function P(e) {
|
|
109
109
|
return e.length === 0 ? e : e[0].toUpperCase() + e.slice(1);
|
|
110
110
|
}
|
|
111
|
-
function
|
|
112
|
-
const n = t.title ?? "API",
|
|
113
|
-
for (const
|
|
114
|
-
const c =
|
|
115
|
-
operationId:
|
|
116
|
-
summary:
|
|
111
|
+
function $(e, t = {}) {
|
|
112
|
+
const n = t.title ?? "API", i = t.version ?? "0.0.0", o = {};
|
|
113
|
+
for (const r of e) {
|
|
114
|
+
const c = x(r), { verb: p, route: s } = c.http, l = p.toLowerCase(), f = {
|
|
115
|
+
operationId: r.id,
|
|
116
|
+
summary: r.id,
|
|
117
117
|
responses: {
|
|
118
|
-
200:
|
|
118
|
+
200: E(r.output)
|
|
119
119
|
}
|
|
120
120
|
};
|
|
121
121
|
if (p === "GET")
|
|
122
|
-
f.parameters = C(
|
|
122
|
+
f.parameters = C(r.input);
|
|
123
123
|
else {
|
|
124
|
-
const u =
|
|
124
|
+
const u = r.input;
|
|
125
125
|
typeof u == "object" && u !== null && Object.keys(u).length > 0 && (f.requestBody = {
|
|
126
126
|
required: !0,
|
|
127
127
|
content: {
|
|
@@ -131,15 +131,15 @@ function E(e, t = {}) {
|
|
|
131
131
|
}
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
o[s] === void 0 && (o[s] = {}), o[s][l] = f;
|
|
135
135
|
}
|
|
136
136
|
return {
|
|
137
137
|
openapi: "3.1.0",
|
|
138
|
-
info: { title: n, version:
|
|
139
|
-
paths:
|
|
138
|
+
info: { title: n, version: i },
|
|
139
|
+
paths: o
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function E(e) {
|
|
143
143
|
return typeof e == "object" && e !== null && Object.keys(e).length > 0 ? {
|
|
144
144
|
description: "Success",
|
|
145
145
|
content: {
|
|
@@ -151,17 +151,17 @@ function C(e) {
|
|
|
151
151
|
if (typeof e != "object" || e === null || typeof e.properties != "object" || e.properties === null)
|
|
152
152
|
return [];
|
|
153
153
|
const t = Array.isArray(e.required) ? e.required : [], n = e.properties;
|
|
154
|
-
return Object.entries(n).map(([
|
|
155
|
-
name:
|
|
154
|
+
return Object.entries(n).map(([i, o]) => ({
|
|
155
|
+
name: i,
|
|
156
156
|
in: "query",
|
|
157
|
-
required: t.includes(
|
|
158
|
-
schema:
|
|
157
|
+
required: t.includes(i),
|
|
158
|
+
schema: o
|
|
159
159
|
}));
|
|
160
160
|
}
|
|
161
|
-
function
|
|
161
|
+
function S(e, t = {}) {
|
|
162
162
|
return [
|
|
163
163
|
{
|
|
164
|
-
...
|
|
164
|
+
...j("_meta/openapi", e, {
|
|
165
165
|
// query + safe → GET /meta/openapi (SPEC §5)
|
|
166
166
|
kind: "query",
|
|
167
167
|
safe: !0,
|
|
@@ -172,7 +172,7 @@ function I(e, t = {}) {
|
|
|
172
172
|
transports: ["http"]
|
|
173
173
|
}),
|
|
174
174
|
// Handler: derive the doc from the descriptor at request time.
|
|
175
|
-
handler: (n) =>
|
|
175
|
+
handler: (n) => $(e.operations, {
|
|
176
176
|
title: t.title,
|
|
177
177
|
version: t.version
|
|
178
178
|
})
|
|
@@ -194,7 +194,7 @@ const B = {
|
|
|
194
194
|
capabilities: {
|
|
195
195
|
mount: {
|
|
196
196
|
operations(e, t) {
|
|
197
|
-
return
|
|
197
|
+
return S(
|
|
198
198
|
e,
|
|
199
199
|
t
|
|
200
200
|
);
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhd/apigen-plugin-openapi",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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.0",
|
|
7
|
+
"@adhd/apigen-codegen-openapi": "^0.2.2"
|
|
8
8
|
},
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|