@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 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 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("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 b(e, t, n = {}) {
12
- const o = e.split("/");
13
- if (o.length < 2 || o.some((l) => l.length === 0))
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 [r, ...i] = o, c = r.replace(/^_+/, ""), p = n.kind ?? "action", s = {
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: i.map(m),
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 j = {
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(j).map(([e, t]) => ({
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((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;
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 x(e) {
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\\(["'][^"']*${x(e)}[^"']*["']\\)\\.\\w+`,
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($).join("");
93
+ return e.words.map(P).join("");
94
94
  }
95
95
  function g(e) {
96
96
  return e.words.join("_");
97
97
  }
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));
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: v }
105
+ cli: { path: b }
106
106
  };
107
107
  }
108
- function $(e) {
108
+ function P(e) {
109
109
  return e.length === 0 ? e : e[0].toUpperCase() + e.slice(1);
110
110
  }
111
- function E(e, t = {}) {
112
- const n = t.title ?? "API", o = t.version ?? "0.0.0", r = {};
113
- for (const i of e) {
114
- const c = k(i), { verb: p, route: s } = c.http, l = p.toLowerCase(), f = {
115
- operationId: i.id,
116
- summary: i.id,
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: P(i.output)
118
+ 200: E(r.output)
119
119
  }
120
120
  };
121
121
  if (p === "GET")
122
- f.parameters = C(i.input);
122
+ f.parameters = C(r.input);
123
123
  else {
124
- const u = i.input;
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
- r[s] === void 0 && (r[s] = {}), r[s][l] = f;
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: o },
139
- paths: r
138
+ info: { title: n, version: i },
139
+ paths: o
140
140
  };
141
141
  }
142
- function P(e) {
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(([o, r]) => ({
155
- name: o,
154
+ return Object.entries(n).map(([i, o]) => ({
155
+ name: i,
156
156
  in: "query",
157
- required: t.includes(o),
158
- schema: r
157
+ required: t.includes(i),
158
+ schema: o
159
159
  }));
160
160
  }
161
- function I(e, t = {}) {
161
+ function S(e, t = {}) {
162
162
  return [
163
163
  {
164
- ...b("_meta/openapi", e, {
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) => E(e.operations, {
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 I(
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.1",
3
+ "version": "0.2.2",
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.0",
7
+ "@adhd/apigen-codegen-openapi": "^0.2.2"
8
8
  },
9
9
  "publishConfig": {
10
10
  "access": "public"