@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 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("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 o=e.split("/");if(o.length<2||o.some(l=>l.length===0))throw new Error(`syntheticOp: id "${e}" must be "<namespace>/<path...>" with non-empty segments`);const[r,...i]=o,c=r.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(o=>d.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(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(S).join("")}function g(e){return e.words.join("_")}function x(e,t={}){var n,o;const r=[e.namespace,...e.path],i=e.safe||A(e.input)?"GET":"POST",c=((o=(n=t.http)==null?void 0:n.verb)==null?void 0:o[e.id])??i,p="/"+r.map(a=>y(a)).join("/"),s=r.map(a=>g(a)).join("_"),l=r.map(a=>g(a)).slice(0,-1).join("."),f=h(r[r.length-2]??r[0]),u=h(r[r.length-1]),b=r.map(a=>y(a));return{http:{verb:c,route:p},mcp:{name:s},grpc:{package:l,service:f,method:u},cli:{path:b}}}function S(e){return e.length===0?e:e[0].toUpperCase()+e.slice(1)}function _(e,t={}){const n=t.title??"API",o=t.version??"0.0.0",r={};for(const i of e){const c=x(i),{verb:p,route:s}=c.http,l=p.toLowerCase(),f={operationId:i.id,summary:i.id,responses:{200:$(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}}})}r[s]===void 0&&(r[s]={}),r[s][l]=f}return{openapi:"3.1.0",info:{title:n,version:o},paths:r}}function $(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(([o,r])=>({name:o,in:"query",required:t.includes(o),schema:r}))}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 v={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=v;exports.openapiPlugin=v;
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 b(e, t, n = {}) {
12
- const o = e.split("/");
13
- if (o.length < 2 || o.some((l) => l.length === 0))
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 [r, ...i] = o, c = r.replace(/^_+/, ""), p = n.kind ?? "action", s = {
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
- const j = {
32
+ b(import.meta.url);
33
+ const O = {
34
34
  "decimal.js": "Decimal"
35
35
  };
36
- function O(e) {
36
+ function w(e) {
37
37
  return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
38
38
  }
39
- Object.entries(j).map(([e, t]) => ({
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\\(["'][^"']*${O(e)}[^"']*["']\\)\\.\\w+`,
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 w(e) {
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((o) => d.has(o) || o === "null") : Array.isArray(t.enum) && t.enum.length > 0 ? t.enum.every((o) => ["string", "number", "boolean"].includes(typeof o)) : !1;
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 A(e) {
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
- w
68
+ A
68
69
  );
69
70
  }
70
- const q = {
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(q).map(([e, t]) => ({
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 k(e, t = {}) {
99
- var n, o;
100
- const r = [e.namespace, ...e.path], i = e.safe || A(e.input) ? "GET" : "POST", c = ((o = (n = t.http) == null ? void 0 : n.verb) == null ? void 0 : o[e.id]) ?? i, p = "/" + r.map((a) => y(a)).join("/"), s = r.map((a) => g(a)).join("_"), l = r.map((a) => g(a)).slice(0, -1).join("."), f = h(r[r.length - 2] ?? r[0]), u = h(r[r.length - 1]), v = r.map((a) => y(a));
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", o = t.version ?? "0.0.0", r = {};
113
+ const n = t.title ?? "API", r = t.version ?? "0.0.0", o = {};
113
114
  for (const i of e) {
114
- const c = k(i), { verb: p, route: s } = c.http, l = p.toLowerCase(), f = {
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
- r[s] === void 0 && (r[s] = {}), r[s][l] = f;
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: o },
139
- paths: r
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(([o, r]) => ({
155
- name: o,
155
+ return Object.entries(n).map(([r, o]) => ({
156
+ name: r,
156
157
  in: "query",
157
- required: t.includes(o),
158
- schema: r
158
+ required: t.includes(r),
159
+ schema: o
159
160
  }));
160
161
  }
161
- function I(e, t = {}) {
162
+ function S(e, t = {}) {
162
163
  return [
163
164
  {
164
- ...b("_meta/openapi", e, {
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 B = {
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 I(
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
- B as default,
207
- B as openapiPlugin
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.1",
3
+ "version": "0.2.3",
4
4
  "main": "./index.js",
5
5
  "dependencies": {
6
- "@adhd/apigen-core-client": "^0.2.1",
7
- "@adhd/apigen-codegen-openapi": "^0.2.1"
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
  }