@omer-x/next-openapi-json-generator 1.0.0 → 1.0.1
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/dist/index.d.ts +11 -0
- package/dist/index.js +323 -1
- package/package.json +5 -9
- package/dist/jest.config.d.ts +0 -3
- package/dist/src/core/dir.d.ts +0 -3
- package/dist/src/core/dir.test.d.ts +0 -1
- package/dist/src/core/generateOpenApiSpec.d.ts +0 -9
- package/dist/src/core/generateOpenApiSpec.test.d.ts +0 -1
- package/dist/src/core/mask.d.ts +0 -3
- package/dist/src/core/mask.test.d.ts +0 -1
- package/dist/src/core/next.d.ts +0 -5
- package/dist/src/core/next.test.d.ts +0 -1
- package/dist/src/core/operation-mask.d.ts +0 -3
- package/dist/src/core/options.d.ts +0 -4
- package/dist/src/core/options.test.d.ts +0 -1
- package/dist/src/core/route.d.ts +0 -10
- package/dist/src/core/route.test.d.ts +0 -1
- package/dist/src/core/schema.d.ts +0 -3
- package/dist/src/core/schema.test.d.ts +0 -1
- package/dist/src/core/transpile.d.ts +0 -1
- package/dist/src/core/transpile.test.d.ts +0 -1
- package/dist/src/core/zod-to-openapi.d.ts +0 -3
- package/dist/src/core/zod-to-openapi.test.d.ts +0 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/utils/deepEqual.d.ts +0 -1
- package/dist/src/utils/deepEqual.test.d.ts +0 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { OpenApiDocument } from '@omer-x/openapi-types';
|
|
2
|
+
import { ZodType } from 'zod';
|
|
3
|
+
|
|
4
|
+
type GeneratorOptions = {
|
|
5
|
+
include?: string[];
|
|
6
|
+
exclude?: string[];
|
|
7
|
+
routeDefinerName?: string;
|
|
8
|
+
};
|
|
9
|
+
declare function generateOpenApiSpec(schemas: Record<string, ZodType>, { include: includeOption, exclude: excludeOption, routeDefinerName, }?: GeneratorOptions): Promise<Omit<OpenApiDocument, "components"> & Required<Pick<OpenApiDocument, "components">>>;
|
|
10
|
+
|
|
11
|
+
export { generateOpenApiSpec as default };
|
package/dist/index.js
CHANGED
|
@@ -1 +1,323 @@
|
|
|
1
|
-
(()=>{var __webpack_modules__={505:t=>{"use strict";function e(t,e,i){t instanceof RegExp&&(t=s(t,i)),e instanceof RegExp&&(e=s(e,i));var n=r(t,e,i);return n&&{start:n[0],end:n[1],pre:i.slice(0,n[0]),body:i.slice(n[0]+t.length,n[1]),post:i.slice(n[1]+e.length)}}function s(t,e){var s=e.match(t);return s?s[0]:null}function r(t,e,s){var r,i,n,o,a,h=s.indexOf(t),p=s.indexOf(e,h+1),c=h;if(h>=0&&p>0){if(t===e)return[h,p];for(r=[],n=s.length;c>=0&&!a;)c==h?(r.push(c),h=s.indexOf(t,c+1)):1==r.length?a=[r.pop(),p]:((i=r.pop())<n&&(n=i,o=p),p=s.indexOf(e,c+1)),c=h<p&&h>=0?h:p;r.length&&(a=[n,o])}return a}t.exports=e,e.range=r},928:(t,e,s)=>{var r=s(505);t.exports=function(t){if(!t)return[];"{}"===t.substr(0,2)&&(t="\\{\\}"+t.substr(2));return m(function(t){return t.split("\\\\").join(i).split("\\{").join(n).split("\\}").join(o).split("\\,").join(a).split("\\.").join(h)}(t),!0).map(c)};var i="\0SLASH"+Math.random()+"\0",n="\0OPEN"+Math.random()+"\0",o="\0CLOSE"+Math.random()+"\0",a="\0COMMA"+Math.random()+"\0",h="\0PERIOD"+Math.random()+"\0";function p(t){return parseInt(t,10)==t?parseInt(t,10):t.charCodeAt(0)}function c(t){return t.split(i).join("\\").split(n).join("{").split(o).join("}").split(a).join(",").split(h).join(".")}function l(t){if(!t)return[""];var e=[],s=r("{","}",t);if(!s)return t.split(",");var i=s.pre,n=s.body,o=s.post,a=i.split(",");a[a.length-1]+="{"+n+"}";var h=l(o);return o.length&&(a[a.length-1]+=h.shift(),a.push.apply(a,h)),e.push.apply(e,a),e}function u(t){return"{"+t+"}"}function f(t){return/^-?0\d/.test(t)}function d(t,e){return t<=e}function g(t,e){return t>=e}function m(t,e){var s=[],i=r("{","}",t);if(!i)return[t];var n=i.pre,a=i.post.length?m(i.post,!1):[""];if(/\$$/.test(i.pre))for(var h=0;h<a.length;h++){var c=n+"{"+i.body+"}"+a[h];s.push(c)}else{var _,b,y=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(i.body),w=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(i.body),v=y||w,x=i.body.indexOf(",")>=0;if(!v&&!x)return i.post.match(/,.*\}/)?m(t=i.pre+"{"+i.body+o+i.post):[t];if(v)_=i.body.split(/\.\./);else if(1===(_=l(i.body)).length&&1===(_=m(_[0],!1).map(u)).length)return a.map((function(t){return i.pre+_[0]+t}));if(v){var S=p(_[0]),O=p(_[1]),M=Math.max(_[0].length,_[1].length),A=3==_.length?Math.abs(p(_[2])):1,P=d;O<S&&(A*=-1,P=g);var j=_.some(f);b=[];for(var E=S;P(E,O);E+=A){var $;if(w)"\\"===($=String.fromCharCode(E))&&($="");else if($=String(E),j){var R=M-$.length;if(R>0){var T=new Array(R+1).join("0");$=E<0?"-"+T+$.slice(1):T+$}}b.push($)}}else{b=[];for(var L=0;L<_.length;L++)b.push.apply(b,m(_[L],!1))}for(L=0;L<b.length;L++)for(h=0;h<a.length;h++){c=n+b[L]+a[h];(!e||v||c)&&s.push(c)}}return s}},489:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.directoryExists=async function(t){try{return await n.default.access(t,i.constants.F_OK),!0}catch(t){return!1}},e.getDirectoryItems=async function t(e,s){const r=[],i=await n.default.readdir(e);for(const a of i){const i=o.default.resolve(e,a);if((await n.default.stat(i)).isDirectory()){const e=await t(i,s);r.push(...e)}else a===s&&r.push(i)}return r},e.filterDirectoryItems=function(t,e,s,r){const i=s.map((t=>new a.Minimatch(t))),n=r.map((t=>new a.Minimatch(t)));return e.filter((e=>{const r=o.default.relative(t,e),a=i.some((t=>t.match(r))),h=n.some((t=>t.match(r)));return(a||!s.length)&&!h}))};const i=s(896),n=r(s(943)),o=r(s(760)),a=s(722)},428:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.default=async function(t,{include:e=[],exclude:s=[],routeDefinerName:r="defineRoute"}={}){const c=(0,a.verifyOptions)(e,s),l=await(0,o.findAppFolderPath)();if(!l)throw new Error("This is not a Next.js application!");const u=await(0,n.getDirectoryItems)(l,"route.ts"),f=(0,n.filterDirectoryItems)(l,u,c.include,c.exclude),d=[];for(const e of f){const s=await(0,o.getRouteExports)(e,r,t);for(const[t,r]of Object.entries(s))r&&r.apiData&&d.push((0,h.createRouteRecord)(t.toLocaleLowerCase(),e,l,r.apiData))}const g=(0,i.default)();return{openapi:"3.1.0",info:{title:g.serviceName,version:g.version},paths:(0,h.bundlePaths)(d,t),components:{schemas:(0,p.bundleSchemas)(t)},tags:[]}};const i=r(s(213)),n=s(489),o=s(37),a=s(664),h=s(683),p=s(744)},580:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.default=function t(e,s,r){if(r)for(const[t,r]of Object.entries(s))if((0,i.default)(e,(0,n.default)(r,!1)))return{$ref:`#/components/schemas/${t}`};if("$ref"in e)return e;if(e.oneOf)return{...e,oneOf:e.oneOf.map((e=>t(e,s,!0)))};if(e.anyOf)return{...e,anyOf:e.anyOf.map((e=>t(e,s,!0)))};switch(e.type){case"object":return{...e,properties:Object.entries(e.properties??{}).reduce(((e,[r,i])=>({...e,[r]:t(i,s,!0)})),{})};case"array":return Array.isArray(e.items)?{...e,items:e.items.map((e=>t(e,s,!0)))}:{...e,items:t(e.items,s,!0)}}return e};const i=r(s(92)),n=r(s(292))},37:function(__unused_webpack_module,exports,__webpack_require__){"use strict";var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.findAppFolderPath=findAppFolderPath,exports.getRouteExports=getRouteExports;const promises_1=__importDefault(__webpack_require__(455)),node_path_1=__importDefault(__webpack_require__(760)),dir_1=__webpack_require__(489),transpile_1=__webpack_require__(380);async function findAppFolderPath(){const t=node_path_1.default.resolve(process.cwd(),"src","app");if(await(0,dir_1.directoryExists)(t))return t;const e=node_path_1.default.resolve(process.cwd(),"app");return await(0,dir_1.directoryExists)(e)?e:null}function injectSchemas(t,e){return t.replace(new RegExp(`\\b${e}\\.`,"g"),`global.schemas[${e}].`).replace(new RegExp(`\\b${e}\\b`,"g"),`"${e}"`)}function safeEval(code,routePath){try{return eval(code)}catch(t){throw console.log(`An error occured while evaluating the route exports from "${routePath}"`),t}}async function getRouteExports(t,e,s){const r=await promises_1.default.readFile(t,"utf-8"),i=(0,transpile_1.transpile)(r,e),n=Object.keys(s).reduce(injectSchemas,i);global.schemas=s;const o=safeEval(n,t);return delete global.schemas,o}},976:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t,e){return{...t,parameters:t.parameters?.map((t=>function(t,e){return"$ref"in t?t:{...t,schema:n(e,t.schema)}}(t,e))),requestBody:a(e,t.requestBody),responses:p(e,t.responses)}};const i=r(s(580));function n(t,e){return e?(0,i.default)(e,t,!0):e}function o(t,e){return e?Object.entries(e).reduce(((e,[s,r])=>({...e,[s]:{...r,schema:n(t,r.schema)}})),{}):e}function a(t,e){return!e||"$ref"in e?e:{...e,content:o(t,e.content)}}function h(t,e){return"$ref"in e?e:{...e,content:o(t,e.content)}}function p(t,e){return e?Object.entries(e).reduce(((e,[s,r])=>({...e,[s]:h(t,r)})),{}):e}},664:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.verifyOptions=function(t,e){0;return{include:t.filter((t=>t.endsWith("/route.ts"))),exclude:e.filter((t=>t.endsWith("/route.ts")))}}},683:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.createRouteRecord=function(t,e,s,r){return{method:t.toLocaleLowerCase(),path:n(e,s),apiData:r}},e.bundlePaths=function(t,e){return t.sort(((t,e)=>t.path.localeCompare(e.path))),t.reduce(((t,s)=>({...t,[s.path]:{...t[s.path],[s.method]:(0,i.default)(s.apiData,e)}})),{})};const i=r(s(976));function n(t,e){return t.replace(e,"").replace("[","{").replace("]","}").replaceAll("\\","/").replace("/route.ts","")}},744:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.bundleSchemas=function(t){const e=Object.keys(t).reduce(((e,s)=>({...e,[s]:(0,n.default)(t[s],!1)})),{});return Object.entries(e).reduce(((e,[s,r])=>({...e,[s]:(0,i.default)(r,t,!1)})),{})};const i=r(s(580)),n=r(s(292))},380:(t,e,s)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.transpile=function(t,e){const s=function(t){const e=["GET","POST","PUT","PATCH","DELETE"],s=e.map((t=>`exports.${t} = void 0;\n`)),r=`module.exports = { ${e.map((t=>`${t}: exports.${t}`)).join(", ")} }`;return`${s}\n${t}\n${r}`}(function(t){return t.replace(/^import\s.+\sfrom\s.+;?$/gm,"").trim()}(t)),i=[`import ${e} from '@omer-x/next-openapi-route-handler';`,"import z from 'zod';",s];return(0,r.transpile)(i.join("\n"))};const r=s(899)},292:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t,e){return(0,i.default)(e?t.array():t,{target:"openApi3",$refStrategy:"none"})};const i=r(s(106))},156:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0});const i=r(s(428));e.default=i.default},92:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=function t(e,s){if(typeof e!=typeof s)return!1;switch(typeof e){case"object":return e&&s?Array.isArray(e)&&Array.isArray(s)?e.every(((e,r)=>t(e,s[r]))):Object.entries(e).every((([e,r])=>t(r,s[e]))):e===s;case"function":case"symbol":return!1;default:return e===s}}},213:t=>{"use strict";t.exports=require("@omer-x/package-metadata")},899:t=>{"use strict";t.exports=require("typescript")},106:t=>{"use strict";t.exports=require("zod-to-json-schema")},896:t=>{"use strict";t.exports=require("fs")},943:t=>{"use strict";t.exports=require("fs/promises")},455:t=>{"use strict";t.exports=require("node:fs/promises")},760:t=>{"use strict";t.exports=require("node:path")},274:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.assertValidPattern=void 0;e.assertValidPattern=t=>{if("string"!=typeof t)throw new TypeError("invalid pattern");if(t.length>65536)throw new TypeError("pattern is too long")}},674:(t,e,s)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AST=void 0;const r=s(843),i=s(116),n=new Set(["!","?","+","*","@"]),o=t=>n.has(t),a="(?!\\.)",h=new Set(["[","."]),p=new Set(["..","."]),c=new Set("().*{}+?[]^$\\!"),l="[^/]",u=l+"*?",f=l+"+?";class d{type;#t;#e;#s=!1;#r=[];#i;#n;#o;#a=!1;#h;#p;#c=!1;constructor(t,e,s={}){this.type=t,t&&(this.#e=!0),this.#i=e,this.#t=this.#i?this.#i.#t:this,this.#h=this.#t===this?s:this.#t.#h,this.#o=this.#t===this?[]:this.#t.#o,"!"!==t||this.#t.#a||this.#o.push(this),this.#n=this.#i?this.#i.#r.length:0}get hasMagic(){if(void 0!==this.#e)return this.#e;for(const t of this.#r)if("string"!=typeof t&&(t.type||t.hasMagic))return this.#e=!0;return this.#e}toString(){return void 0!==this.#p?this.#p:this.type?this.#p=this.type+"("+this.#r.map((t=>String(t))).join("|")+")":this.#p=this.#r.map((t=>String(t))).join("")}#l(){if(this!==this.#t)throw new Error("should only call on root");if(this.#a)return this;let t;for(this.toString(),this.#a=!0;t=this.#o.pop();){if("!"!==t.type)continue;let e=t,s=e.#i;for(;s;){for(let r=e.#n+1;!s.type&&r<s.#r.length;r++)for(const e of t.#r){if("string"==typeof e)throw new Error("string part in extglob AST??");e.copyIn(s.#r[r])}e=s,s=e.#i}}return this}push(...t){for(const e of t)if(""!==e){if("string"!=typeof e&&!(e instanceof d&&e.#i===this))throw new Error("invalid part: "+e);this.#r.push(e)}}toJSON(){const t=null===this.type?this.#r.slice().map((t=>"string"==typeof t?t:t.toJSON())):[this.type,...this.#r.map((t=>t.toJSON()))];return this.isStart()&&!this.type&&t.unshift([]),this.isEnd()&&(this===this.#t||this.#t.#a&&"!"===this.#i?.type)&&t.push({}),t}isStart(){if(this.#t===this)return!0;if(!this.#i?.isStart())return!1;if(0===this.#n)return!0;const t=this.#i;for(let e=0;e<this.#n;e++){const s=t.#r[e];if(!(s instanceof d&&"!"===s.type))return!1}return!0}isEnd(){if(this.#t===this)return!0;if("!"===this.#i?.type)return!0;if(!this.#i?.isEnd())return!1;if(!this.type)return this.#i?.isEnd();const t=this.#i?this.#i.#r.length:0;return this.#n===t-1}copyIn(t){"string"==typeof t?this.push(t):this.push(t.clone(this))}clone(t){const e=new d(this.type,t);for(const t of this.#r)e.copyIn(t);return e}static#u(t,e,s,r){let i=!1,n=!1,a=-1,h=!1;if(null===e.type){let p=s,c="";for(;p<t.length;){const s=t.charAt(p++);if(i||"\\"===s)i=!i,c+=s;else if(n)p===a+1?"^"!==s&&"!"!==s||(h=!0):"]"!==s||p===a+2&&h||(n=!1),c+=s;else if("["!==s)if(r.noext||!o(s)||"("!==t.charAt(p))c+=s;else{e.push(c),c="";const i=new d(s,e);p=d.#u(t,i,p,r),e.push(i)}else n=!0,a=p,h=!1,c+=s}return e.push(c),p}let p=s+1,c=new d(null,e);const l=[];let u="";for(;p<t.length;){const s=t.charAt(p++);if(i||"\\"===s)i=!i,u+=s;else if(n)p===a+1?"^"!==s&&"!"!==s||(h=!0):"]"!==s||p===a+2&&h||(n=!1),u+=s;else if("["!==s)if(o(s)&&"("===t.charAt(p)){c.push(u),u="";const e=new d(s,c);c.push(e),p=d.#u(t,e,p,r)}else if("|"!==s){if(")"===s)return""===u&&0===e.#r.length&&(e.#c=!0),c.push(u),u="",e.push(...l,c),p;u+=s}else c.push(u),u="",l.push(c),c=new d(null,e);else n=!0,a=p,h=!1,u+=s}return e.type=null,e.#e=void 0,e.#r=[t.substring(s-1)],p}static fromGlob(t,e={}){const s=new d(null,void 0,e);return d.#u(t,s,0,e),s}toMMPattern(){if(this!==this.#t)return this.#t.toMMPattern();const t=this.toString(),[e,s,r,i]=this.toRegExpSource();if(!(r||this.#e||this.#h.nocase&&!this.#h.nocaseMagicOnly&&t.toUpperCase()!==t.toLowerCase()))return s;const n=(this.#h.nocase?"i":"")+(i?"u":"");return Object.assign(new RegExp(`^${e}$`,n),{_src:e,_glob:t})}get options(){return this.#h}toRegExpSource(t){const e=t??!!this.#h.dot;if(this.#t===this&&this.#l(),!this.type){const s=this.isStart()&&this.isEnd(),r=this.#r.map((e=>{const[r,i,n,o]="string"==typeof e?d.#f(e,this.#e,s):e.toRegExpSource(t);return this.#e=this.#e||n,this.#s=this.#s||o,r})).join("");let n="";if(this.isStart()&&"string"==typeof this.#r[0]){if(!(1===this.#r.length&&p.has(this.#r[0]))){const s=h,i=e&&s.has(r.charAt(0))||r.startsWith("\\.")&&s.has(r.charAt(2))||r.startsWith("\\.\\.")&&s.has(r.charAt(4)),o=!e&&!t&&s.has(r.charAt(0));n=i?"(?!(?:^|/)\\.\\.?(?:$|/))":o?a:""}}let o="";this.isEnd()&&this.#t.#a&&"!"===this.#i?.type&&(o="(?:$|\\/)");return[n+r+o,(0,i.unescape)(r),this.#e=!!this.#e,this.#s]}const s="*"===this.type||"+"===this.type,r="!"===this.type?"(?:(?!(?:":"(?:";let n=this.#d(e);if(this.isStart()&&this.isEnd()&&!n&&"!"!==this.type){const t=this.toString();return this.#r=[t],this.type=null,this.#e=void 0,[t,(0,i.unescape)(this.toString()),!1,!1]}let o=!s||t||e?"":this.#d(!0);o===n&&(o=""),o&&(n=`(?:${n})(?:${o})*?`);let c="";if("!"===this.type&&this.#c)c=(this.isStart()&&!e?a:"")+f;else{c=r+n+("!"===this.type?"))"+(!this.isStart()||e||t?"":a)+u+")":"@"===this.type?")":"?"===this.type?")?":"+"===this.type&&o?")":"*"===this.type&&o?")?":`)${this.type}`)}return[c,(0,i.unescape)(n),this.#e=!!this.#e,this.#s]}#d(t){return this.#r.map((e=>{if("string"==typeof e)throw new Error("string type in extglob ast??");const[s,r,i,n]=e.toRegExpSource(t);return this.#s=this.#s||n,s})).filter((t=>!(this.isStart()&&this.isEnd()&&!t))).join("|")}static#f(t,e,s=!1){let n=!1,o="",a=!1;for(let i=0;i<t.length;i++){const h=t.charAt(i);if(n)n=!1,o+=(c.has(h)?"\\":"")+h;else if("\\"!==h){if("["===h){const[s,n,h,p]=(0,r.parseClass)(t,i);if(h){o+=s,a=a||n,i+=h-1,e=e||p;continue}}"*"!==h?"?"!==h?o+=h.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"):(o+=l,e=!0):(o+=s&&"*"===t?f:u,e=!0)}else i===t.length-1?o+="\\\\":n=!0}return[o,(0,i.unescape)(t),!!e,a]}}e.AST=d},843:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.parseClass=void 0;const s={"[:alnum:]":["\\p{L}\\p{Nl}\\p{Nd}",!0],"[:alpha:]":["\\p{L}\\p{Nl}",!0],"[:ascii:]":["\\x00-\\x7f",!1],"[:blank:]":["\\p{Zs}\\t",!0],"[:cntrl:]":["\\p{Cc}",!0],"[:digit:]":["\\p{Nd}",!0],"[:graph:]":["\\p{Z}\\p{C}",!0,!0],"[:lower:]":["\\p{Ll}",!0],"[:print:]":["\\p{C}",!0],"[:punct:]":["\\p{P}",!0],"[:space:]":["\\p{Z}\\t\\r\\n\\v\\f",!0],"[:upper:]":["\\p{Lu}",!0],"[:word:]":["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}",!0],"[:xdigit:]":["A-Fa-f0-9",!1]},r=t=>t.replace(/[[\]\\-]/g,"\\$&"),i=t=>t.join("");e.parseClass=(t,e)=>{const n=e;if("["!==t.charAt(n))throw new Error("not in a brace expression");const o=[],a=[];let h=n+1,p=!1,c=!1,l=!1,u=!1,f=n,d="";t:for(;h<t.length;){const e=t.charAt(h);if("!"!==e&&"^"!==e||h!==n+1){if("]"===e&&p&&!l){f=h+1;break}if(p=!0,"\\"!==e||l){if("["===e&&!l)for(const[e,[r,i,p]]of Object.entries(s))if(t.startsWith(e,h)){if(d)return["$.",!1,t.length-n,!0];h+=e.length,p?a.push(r):o.push(r),c=c||i;continue t}l=!1,d?(e>d?o.push(r(d)+"-"+r(e)):e===d&&o.push(r(e)),d="",h++):t.startsWith("-]",h+1)?(o.push(r(e+"-")),h+=2):t.startsWith("-",h+1)?(d=e,h+=2):(o.push(r(e)),h++)}else l=!0,h++}else u=!0,h++}if(f<h)return["",!1,0,!1];if(!o.length&&!a.length)return["$.",!1,t.length-n,!0];if(0===a.length&&1===o.length&&/^\\?.$/.test(o[0])&&!u){const t=2===o[0].length?o[0].slice(-1):o[0];return[(g=t,g.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")),!1,f-n,!1]}var g;const m="["+(u?"^":"")+i(o)+"]",_="["+(u?"":"^")+i(a)+"]";return[o.length&&a.length?"("+m+"|"+_+")":o.length?m:_,c,f-n,!0]}},363:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.escape=void 0;e.escape=(t,{windowsPathsNoEscape:e=!1}={})=>e?t.replace(/[?*()[\]]/g,"[$&]"):t.replace(/[?*()[\]\\]/g,"\\$&")},722:function(t,e,s){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0}),e.unescape=e.escape=e.AST=e.Minimatch=e.match=e.makeRe=e.braceExpand=e.defaults=e.filter=e.GLOBSTAR=e.sep=e.minimatch=void 0;const i=r(s(928)),n=s(274),o=s(674),a=s(363),h=s(116);e.minimatch=(t,e,s={})=>((0,n.assertValidPattern)(e),!(!s.nocomment&&"#"===e.charAt(0))&&new N(e,s).match(t));const p=/^\*+([^+@!?\*\[\(]*)$/,c=t=>e=>!e.startsWith(".")&&e.endsWith(t),l=t=>e=>e.endsWith(t),u=t=>(t=t.toLowerCase(),e=>!e.startsWith(".")&&e.toLowerCase().endsWith(t)),f=t=>(t=t.toLowerCase(),e=>e.toLowerCase().endsWith(t)),d=/^\*+\.\*+$/,g=t=>!t.startsWith(".")&&t.includes("."),m=t=>"."!==t&&".."!==t&&t.includes("."),_=/^\.\*+$/,b=t=>"."!==t&&".."!==t&&t.startsWith("."),y=/^\*+$/,w=t=>0!==t.length&&!t.startsWith("."),v=t=>0!==t.length&&"."!==t&&".."!==t,x=/^\?+([^+@!?\*\[\(]*)?$/,S=([t,e=""])=>{const s=P([t]);return e?(e=e.toLowerCase(),t=>s(t)&&t.toLowerCase().endsWith(e)):s},O=([t,e=""])=>{const s=j([t]);return e?(e=e.toLowerCase(),t=>s(t)&&t.toLowerCase().endsWith(e)):s},M=([t,e=""])=>{const s=j([t]);return e?t=>s(t)&&t.endsWith(e):s},A=([t,e=""])=>{const s=P([t]);return e?t=>s(t)&&t.endsWith(e):s},P=([t])=>{const e=t.length;return t=>t.length===e&&!t.startsWith(".")},j=([t])=>{const e=t.length;return t=>t.length===e&&"."!==t&&".."!==t},E="object"==typeof process&&process?"object"==typeof process.env&&process.env&&process.env.__MINIMATCH_TESTING_PLATFORM__||process.platform:"posix",$={sep:"\\"},R={sep:"/"};e.sep="win32"===E?$.sep:R.sep,e.minimatch.sep=e.sep,e.GLOBSTAR=Symbol("globstar **"),e.minimatch.GLOBSTAR=e.GLOBSTAR;e.filter=(t,s={})=>r=>(0,e.minimatch)(r,t,s),e.minimatch.filter=e.filter;const T=(t,e={})=>Object.assign({},t,e);e.defaults=t=>{if(!t||"object"!=typeof t||!Object.keys(t).length)return e.minimatch;const s=e.minimatch;return Object.assign(((e,r,i={})=>s(e,r,T(t,i))),{Minimatch:class extends s.Minimatch{constructor(e,s={}){super(e,T(t,s))}static defaults(e){return s.defaults(T(t,e)).Minimatch}},AST:class extends s.AST{constructor(e,s,r={}){super(e,s,T(t,r))}static fromGlob(e,r={}){return s.AST.fromGlob(e,T(t,r))}},unescape:(e,r={})=>s.unescape(e,T(t,r)),escape:(e,r={})=>s.escape(e,T(t,r)),filter:(e,r={})=>s.filter(e,T(t,r)),defaults:e=>s.defaults(T(t,e)),makeRe:(e,r={})=>s.makeRe(e,T(t,r)),braceExpand:(e,r={})=>s.braceExpand(e,T(t,r)),match:(e,r,i={})=>s.match(e,r,T(t,i)),sep:s.sep,GLOBSTAR:e.GLOBSTAR})},e.minimatch.defaults=e.defaults;e.braceExpand=(t,e={})=>((0,n.assertValidPattern)(t),e.nobrace||!/\{(?:(?!\{).)*\}/.test(t)?[t]:(0,i.default)(t)),e.minimatch.braceExpand=e.braceExpand;e.makeRe=(t,e={})=>new N(t,e).makeRe(),e.minimatch.makeRe=e.makeRe;e.match=(t,e,s={})=>{const r=new N(e,s);return t=t.filter((t=>r.match(t))),r.options.nonull&&!t.length&&t.push(e),t},e.minimatch.match=e.match;const L=/[?*]|[+@!]\(.*?\)|\[|\]/;class N{options;set;pattern;windowsPathsNoEscape;nonegate;negate;comment;empty;preserveMultipleSlashes;partial;globSet;globParts;nocase;isWindows;platform;windowsNoMagicRoot;regexp;constructor(t,e={}){(0,n.assertValidPattern)(t),e=e||{},this.options=e,this.pattern=t,this.platform=e.platform||E,this.isWindows="win32"===this.platform,this.windowsPathsNoEscape=!!e.windowsPathsNoEscape||!1===e.allowWindowsEscape,this.windowsPathsNoEscape&&(this.pattern=this.pattern.replace(/\\/g,"/")),this.preserveMultipleSlashes=!!e.preserveMultipleSlashes,this.regexp=null,this.negate=!1,this.nonegate=!!e.nonegate,this.comment=!1,this.empty=!1,this.partial=!!e.partial,this.nocase=!!this.options.nocase,this.windowsNoMagicRoot=void 0!==e.windowsNoMagicRoot?e.windowsNoMagicRoot:!(!this.isWindows||!this.nocase),this.globSet=[],this.globParts=[],this.set=[],this.make()}hasMagic(){if(this.options.magicalBraces&&this.set.length>1)return!0;for(const t of this.set)for(const e of t)if("string"!=typeof e)return!0;return!1}debug(...t){}make(){const t=this.pattern,e=this.options;if(!e.nocomment&&"#"===t.charAt(0))return void(this.comment=!0);if(!t)return void(this.empty=!0);this.parseNegate(),this.globSet=[...new Set(this.braceExpand())],e.debug&&(this.debug=(...t)=>console.error(...t)),this.debug(this.pattern,this.globSet);const s=this.globSet.map((t=>this.slashSplit(t)));this.globParts=this.preprocess(s),this.debug(this.pattern,this.globParts);let r=this.globParts.map(((t,e,s)=>{if(this.isWindows&&this.windowsNoMagicRoot){const e=!(""!==t[0]||""!==t[1]||"?"!==t[2]&&L.test(t[2])||L.test(t[3])),s=/^[a-z]:/i.test(t[0]);if(e)return[...t.slice(0,4),...t.slice(4).map((t=>this.parse(t)))];if(s)return[t[0],...t.slice(1).map((t=>this.parse(t)))]}return t.map((t=>this.parse(t)))}));if(this.debug(this.pattern,r),this.set=r.filter((t=>-1===t.indexOf(!1))),this.isWindows)for(let t=0;t<this.set.length;t++){const e=this.set[t];""===e[0]&&""===e[1]&&"?"===this.globParts[t][2]&&"string"==typeof e[3]&&/^[a-z]:$/i.test(e[3])&&(e[2]="?")}this.debug(this.pattern,this.set)}preprocess(t){if(this.options.noglobstar)for(let e=0;e<t.length;e++)for(let s=0;s<t[e].length;s++)"**"===t[e][s]&&(t[e][s]="*");const{optimizationLevel:e=1}=this.options;return e>=2?(t=this.firstPhasePreProcess(t),t=this.secondPhasePreProcess(t)):t=e>=1?this.levelOneOptimize(t):this.adjascentGlobstarOptimize(t),t}adjascentGlobstarOptimize(t){return t.map((t=>{let e=-1;for(;-1!==(e=t.indexOf("**",e+1));){let s=e;for(;"**"===t[s+1];)s++;s!==e&&t.splice(e,s-e)}return t}))}levelOneOptimize(t){return t.map((t=>0===(t=t.reduce(((t,e)=>{const s=t[t.length-1];return"**"===e&&"**"===s?t:".."===e&&s&&".."!==s&&"."!==s&&"**"!==s?(t.pop(),t):(t.push(e),t)}),[])).length?[""]:t))}levelTwoFileOptimize(t){Array.isArray(t)||(t=this.slashSplit(t));let e=!1;do{if(e=!1,!this.preserveMultipleSlashes){for(let s=1;s<t.length-1;s++){const r=t[s];1===s&&""===r&&""===t[0]||("."!==r&&""!==r||(e=!0,t.splice(s,1),s--))}"."!==t[0]||2!==t.length||"."!==t[1]&&""!==t[1]||(e=!0,t.pop())}let s=0;for(;-1!==(s=t.indexOf("..",s+1));){const r=t[s-1];r&&"."!==r&&".."!==r&&"**"!==r&&(e=!0,t.splice(s-1,2),s-=2)}}while(e);return 0===t.length?[""]:t}firstPhasePreProcess(t){let e=!1;do{e=!1;for(let s of t){let r=-1;for(;-1!==(r=s.indexOf("**",r+1));){let i=r;for(;"**"===s[i+1];)i++;i>r&&s.splice(r+1,i-r);let n=s[r+1];const o=s[r+2],a=s[r+3];if(".."!==n)continue;if(!o||"."===o||".."===o||!a||"."===a||".."===a)continue;e=!0,s.splice(r,1);const h=s.slice(0);h[r]="**",t.push(h),r--}if(!this.preserveMultipleSlashes){for(let t=1;t<s.length-1;t++){const r=s[t];1===t&&""===r&&""===s[0]||("."!==r&&""!==r||(e=!0,s.splice(t,1),t--))}"."!==s[0]||2!==s.length||"."!==s[1]&&""!==s[1]||(e=!0,s.pop())}let i=0;for(;-1!==(i=s.indexOf("..",i+1));){const t=s[i-1];if(t&&"."!==t&&".."!==t&&"**"!==t){e=!0;const t=1===i&&"**"===s[i+1]?["."]:[];s.splice(i-1,2,...t),0===s.length&&s.push(""),i-=2}}}}while(e);return t}secondPhasePreProcess(t){for(let e=0;e<t.length-1;e++)for(let s=e+1;s<t.length;s++){const r=this.partsMatch(t[e],t[s],!this.preserveMultipleSlashes);if(r){t[e]=[],t[s]=r;break}}return t.filter((t=>t.length))}partsMatch(t,e,s=!1){let r=0,i=0,n=[],o="";for(;r<t.length&&i<e.length;)if(t[r]===e[i])n.push("b"===o?e[i]:t[r]),r++,i++;else if(s&&"**"===t[r]&&e[i]===t[r+1])n.push(t[r]),r++;else if(s&&"**"===e[i]&&t[r]===e[i+1])n.push(e[i]),i++;else if("*"!==t[r]||!e[i]||!this.options.dot&&e[i].startsWith(".")||"**"===e[i]){if("*"!==e[i]||!t[r]||!this.options.dot&&t[r].startsWith(".")||"**"===t[r])return!1;if("a"===o)return!1;o="b",n.push(e[i]),r++,i++}else{if("b"===o)return!1;o="a",n.push(t[r]),r++,i++}return t.length===e.length&&n}parseNegate(){if(this.nonegate)return;const t=this.pattern;let e=!1,s=0;for(let r=0;r<t.length&&"!"===t.charAt(r);r++)e=!e,s++;s&&(this.pattern=t.slice(s)),this.negate=e}matchOne(t,s,r=!1){const i=this.options;if(this.isWindows){const e="string"==typeof t[0]&&/^[a-z]:$/i.test(t[0]),r=!e&&""===t[0]&&""===t[1]&&"?"===t[2]&&/^[a-z]:$/i.test(t[3]),i="string"==typeof s[0]&&/^[a-z]:$/i.test(s[0]),n=r?3:e?0:void 0,o=!i&&""===s[0]&&""===s[1]&&"?"===s[2]&&"string"==typeof s[3]&&/^[a-z]:$/i.test(s[3])?3:i?0:void 0;if("number"==typeof n&&"number"==typeof o){const[e,r]=[t[n],s[o]];e.toLowerCase()===r.toLowerCase()&&(s[o]=e,o>n?s=s.slice(o):n>o&&(t=t.slice(n)))}}const{optimizationLevel:n=1}=this.options;n>=2&&(t=this.levelTwoFileOptimize(t)),this.debug("matchOne",this,{file:t,pattern:s}),this.debug("matchOne",t.length,s.length);for(var o=0,a=0,h=t.length,p=s.length;o<h&&a<p;o++,a++){this.debug("matchOne loop");var c=s[a],l=t[o];if(this.debug(s,c,l),!1===c)return!1;if(c===e.GLOBSTAR){this.debug("GLOBSTAR",[s,c,l]);var u=o,f=a+1;if(f===p){for(this.debug("** at the end");o<h;o++)if("."===t[o]||".."===t[o]||!i.dot&&"."===t[o].charAt(0))return!1;return!0}for(;u<h;){var d=t[u];if(this.debug("\nglobstar while",t,u,s,f,d),this.matchOne(t.slice(u),s.slice(f),r))return this.debug("globstar found match!",u,h,d),!0;if("."===d||".."===d||!i.dot&&"."===d.charAt(0)){this.debug("dot detected!",t,u,s,f);break}this.debug("globstar swallow a segment, and continue"),u++}return!(!r||(this.debug("\n>>> no match, partial?",t,u,s,f),u!==h))}let n;if("string"==typeof c?(n=l===c,this.debug("string match",c,l,n)):(n=c.test(l),this.debug("pattern match",c,l,n)),!n)return!1}if(o===h&&a===p)return!0;if(o===h)return r;if(a===p)return o===h-1&&""===t[o];throw new Error("wtf?")}braceExpand(){return(0,e.braceExpand)(this.pattern,this.options)}parse(t){(0,n.assertValidPattern)(t);const s=this.options;if("**"===t)return e.GLOBSTAR;if(""===t)return"";let r,i=null;(r=t.match(y))?i=s.dot?v:w:(r=t.match(p))?i=(s.nocase?s.dot?f:u:s.dot?l:c)(r[1]):(r=t.match(x))?i=(s.nocase?s.dot?O:S:s.dot?M:A)(r):(r=t.match(d))?i=s.dot?m:g:(r=t.match(_))&&(i=b);const a=o.AST.fromGlob(t,this.options).toMMPattern();return i&&"object"==typeof a&&Reflect.defineProperty(a,"test",{value:i}),a}makeRe(){if(this.regexp||!1===this.regexp)return this.regexp;const t=this.set;if(!t.length)return this.regexp=!1,this.regexp;const s=this.options,r=s.noglobstar?"[^/]*?":s.dot?"(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?":"(?:(?!(?:\\/|^)\\.).)*?",i=new Set(s.nocase?["i"]:[]);let n=t.map((t=>{const s=t.map((t=>{if(t instanceof RegExp)for(const e of t.flags.split(""))i.add(e);return"string"==typeof t?t.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"):t===e.GLOBSTAR?e.GLOBSTAR:t._src}));return s.forEach(((t,i)=>{const n=s[i+1],o=s[i-1];t===e.GLOBSTAR&&o!==e.GLOBSTAR&&(void 0===o?void 0!==n&&n!==e.GLOBSTAR?s[i+1]="(?:\\/|"+r+"\\/)?"+n:s[i]=r:void 0===n?s[i-1]=o+"(?:\\/|"+r+")?":n!==e.GLOBSTAR&&(s[i-1]=o+"(?:\\/|\\/"+r+"\\/)"+n,s[i+1]=e.GLOBSTAR))})),s.filter((t=>t!==e.GLOBSTAR)).join("/")})).join("|");const[o,a]=t.length>1?["(?:",")"]:["",""];n="^"+o+n+a+"$",this.negate&&(n="^(?!"+n+").+$");try{this.regexp=new RegExp(n,[...i].join(""))}catch(t){this.regexp=!1}return this.regexp}slashSplit(t){return this.preserveMultipleSlashes?t.split("/"):this.isWindows&&/^\/\/[^\/]+/.test(t)?["",...t.split(/\/+/)]:t.split(/\/+/)}match(t,e=this.partial){if(this.debug("match",t,this.pattern),this.comment)return!1;if(this.empty)return""===t;if("/"===t&&e)return!0;const s=this.options;this.isWindows&&(t=t.split("\\").join("/"));const r=this.slashSplit(t);this.debug(this.pattern,"split",r);const i=this.set;this.debug(this.pattern,"set",i);let n=r[r.length-1];if(!n)for(let t=r.length-2;!n&&t>=0;t--)n=r[t];for(let t=0;t<i.length;t++){const o=i[t];let a=r;s.matchBase&&1===o.length&&(a=[n]);if(this.matchOne(a,o,e))return!!s.flipNegate||!this.negate}return!s.flipNegate&&this.negate}static defaults(t){return e.minimatch.defaults(t).Minimatch}}e.Minimatch=N;var k=s(674);Object.defineProperty(e,"AST",{enumerable:!0,get:function(){return k.AST}});var W=s(363);Object.defineProperty(e,"escape",{enumerable:!0,get:function(){return W.escape}});var C=s(116);Object.defineProperty(e,"unescape",{enumerable:!0,get:function(){return C.unescape}}),e.minimatch.AST=o.AST,e.minimatch.Minimatch=N,e.minimatch.escape=a.escape,e.minimatch.unescape=h.unescape},116:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.unescape=void 0;e.unescape=(t,{windowsPathsNoEscape:e=!1}={})=>e?t.replace(/\[([^\/\\])\]/g,"$1"):t.replace(/((?!\\).|^)\[([^\/\\])\]/g,"$1$2").replace(/\\([^\/])/g,"$1")}},__webpack_module_cache__={};function __webpack_require__(t){var e=__webpack_module_cache__[t];if(void 0!==e)return e.exports;var s=__webpack_module_cache__[t]={exports:{}};return __webpack_modules__[t].call(s.exports,s,s.exports,__webpack_require__),s.exports}var __webpack_exports__=__webpack_require__(156);module.exports=__webpack_exports__})();
|
|
1
|
+
// src/core/generateOpenApiSpec.ts
|
|
2
|
+
import getPackageMetadata from "@omer-x/package-metadata";
|
|
3
|
+
|
|
4
|
+
// src/core/dir.ts
|
|
5
|
+
import { constants } from "fs";
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { Minimatch } from "minimatch";
|
|
9
|
+
async function directoryExists(dirPath) {
|
|
10
|
+
try {
|
|
11
|
+
await fs.access(dirPath, constants.F_OK);
|
|
12
|
+
return true;
|
|
13
|
+
} catch (err) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function getDirectoryItems(dirPath, targetFileName) {
|
|
18
|
+
const collection = [];
|
|
19
|
+
const files = await fs.readdir(dirPath);
|
|
20
|
+
for (const itemName of files) {
|
|
21
|
+
const itemPath = path.resolve(dirPath, itemName);
|
|
22
|
+
const stats = await fs.stat(itemPath);
|
|
23
|
+
if (stats.isDirectory()) {
|
|
24
|
+
const children = await getDirectoryItems(itemPath, targetFileName);
|
|
25
|
+
collection.push(...children);
|
|
26
|
+
} else if (itemName === targetFileName) {
|
|
27
|
+
collection.push(itemPath);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return collection;
|
|
31
|
+
}
|
|
32
|
+
function filterDirectoryItems(rootPath, items, include, exclude) {
|
|
33
|
+
const includedPatterns = include.map((pattern) => new Minimatch(pattern));
|
|
34
|
+
const excludedPatterns = exclude.map((pattern) => new Minimatch(pattern));
|
|
35
|
+
return items.filter((item) => {
|
|
36
|
+
const relativePath = path.relative(rootPath, item);
|
|
37
|
+
const isIncluded = includedPatterns.some((pattern) => pattern.match(relativePath));
|
|
38
|
+
const isExcluded = excludedPatterns.some((pattern) => pattern.match(relativePath));
|
|
39
|
+
return (isIncluded || !include.length) && !isExcluded;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/core/next.ts
|
|
44
|
+
import fs2 from "node:fs/promises";
|
|
45
|
+
import path2 from "node:path";
|
|
46
|
+
|
|
47
|
+
// src/core/transpile.ts
|
|
48
|
+
import { transpile as tsTranspile } from "typescript";
|
|
49
|
+
function removeImports(code2) {
|
|
50
|
+
return code2.replace(/^import\s.+\sfrom\s.+;?$/gm, "").trim();
|
|
51
|
+
}
|
|
52
|
+
function fixExports(code2) {
|
|
53
|
+
const validMethods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
54
|
+
const exportFixer1 = validMethods.map((method) => `exports.${method} = void 0;
|
|
55
|
+
`);
|
|
56
|
+
const exportFixer2 = `module.exports = { ${validMethods.map((m) => `${m}: exports.${m}`).join(", ")} }`;
|
|
57
|
+
return `${exportFixer1}
|
|
58
|
+
${code2}
|
|
59
|
+
${exportFixer2}`;
|
|
60
|
+
}
|
|
61
|
+
function transpile(rawCode, routeDefinerName) {
|
|
62
|
+
const code2 = fixExports(removeImports(rawCode));
|
|
63
|
+
const parts = [
|
|
64
|
+
`import ${routeDefinerName} from '@omer-x/next-openapi-route-handler';`,
|
|
65
|
+
"import z from 'zod';",
|
|
66
|
+
code2
|
|
67
|
+
];
|
|
68
|
+
return tsTranspile(parts.join("\n"));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/core/next.ts
|
|
72
|
+
async function findAppFolderPath() {
|
|
73
|
+
const inSrc = path2.resolve(process.cwd(), "src", "app");
|
|
74
|
+
if (await directoryExists(inSrc)) {
|
|
75
|
+
return inSrc;
|
|
76
|
+
}
|
|
77
|
+
const inRoot = path2.resolve(process.cwd(), "app");
|
|
78
|
+
if (await directoryExists(inRoot)) {
|
|
79
|
+
return inRoot;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
function injectSchemas(code2, refName) {
|
|
84
|
+
return code2.replace(new RegExp(`\\b${refName}\\.`, "g"), `global.schemas[${refName}].`).replace(new RegExp(`\\b${refName}\\b`, "g"), `"${refName}"`);
|
|
85
|
+
}
|
|
86
|
+
function safeEval(code, routePath) {
|
|
87
|
+
try {
|
|
88
|
+
return eval(code);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.log(`An error occured while evaluating the route exports from "${routePath}"`);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function getRouteExports(routePath2, routeDefinerName, schemas) {
|
|
95
|
+
const content = await fs2.readFile(routePath2, "utf-8");
|
|
96
|
+
const code2 = transpile(content, routeDefinerName);
|
|
97
|
+
const fixedCode = Object.keys(schemas).reduce(injectSchemas, code2);
|
|
98
|
+
global.schemas = schemas;
|
|
99
|
+
const result = safeEval(fixedCode, routePath2);
|
|
100
|
+
delete global.schemas;
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/core/options.ts
|
|
105
|
+
function verifyOptions(include, exclude) {
|
|
106
|
+
if (process.env.NODE_ENV === "development") {
|
|
107
|
+
for (const item of include) {
|
|
108
|
+
if (!item.endsWith("/route.ts")) {
|
|
109
|
+
console.log(`${item} is not a valid route handler path`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
for (const item of exclude) {
|
|
113
|
+
if (!item.endsWith("/route.ts")) {
|
|
114
|
+
console.log(`${item} is not a valid route handler path`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
include: include.filter((item) => item.endsWith("/route.ts")),
|
|
120
|
+
exclude: exclude.filter((item) => item.endsWith("/route.ts"))
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/utils/deepEqual.ts
|
|
125
|
+
function deepEqual(a, b) {
|
|
126
|
+
if (typeof a !== typeof b) return false;
|
|
127
|
+
switch (typeof a) {
|
|
128
|
+
case "object": {
|
|
129
|
+
if (!a || !b) return a === b;
|
|
130
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
131
|
+
return a.every((item, index) => deepEqual(item, b[index]));
|
|
132
|
+
}
|
|
133
|
+
return Object.entries(a).every(([key, value]) => deepEqual(value, b[key]));
|
|
134
|
+
}
|
|
135
|
+
case "function":
|
|
136
|
+
case "symbol":
|
|
137
|
+
return false;
|
|
138
|
+
default:
|
|
139
|
+
return a === b;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/core/zod-to-openapi.ts
|
|
144
|
+
import zodToJsonSchema from "zod-to-json-schema";
|
|
145
|
+
function convertToOpenAPI(schema, isArray) {
|
|
146
|
+
const result = zodToJsonSchema(isArray ? schema.array() : schema, {
|
|
147
|
+
target: "openApi3",
|
|
148
|
+
$refStrategy: "none"
|
|
149
|
+
});
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/core/mask.ts
|
|
154
|
+
function maskWithReference(schema, storedSchemas, self) {
|
|
155
|
+
if (self) {
|
|
156
|
+
for (const [schemaName, zodSchema] of Object.entries(storedSchemas)) {
|
|
157
|
+
if (deepEqual(schema, convertToOpenAPI(zodSchema, false))) {
|
|
158
|
+
return {
|
|
159
|
+
$ref: `#/components/schemas/${schemaName}`
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if ("$ref" in schema) return schema;
|
|
165
|
+
if (schema.oneOf) {
|
|
166
|
+
return {
|
|
167
|
+
...schema,
|
|
168
|
+
oneOf: schema.oneOf.map((i) => maskWithReference(i, storedSchemas, true))
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (schema.anyOf) {
|
|
172
|
+
return {
|
|
173
|
+
...schema,
|
|
174
|
+
anyOf: schema.anyOf.map((i) => maskWithReference(i, storedSchemas, true))
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
switch (schema.type) {
|
|
178
|
+
case "object":
|
|
179
|
+
return {
|
|
180
|
+
...schema,
|
|
181
|
+
properties: Object.entries(schema.properties ?? {}).reduce((props, [propName, prop]) => ({
|
|
182
|
+
...props,
|
|
183
|
+
[propName]: maskWithReference(prop, storedSchemas, true)
|
|
184
|
+
}), {})
|
|
185
|
+
};
|
|
186
|
+
case "array":
|
|
187
|
+
if (Array.isArray(schema.items)) {
|
|
188
|
+
return {
|
|
189
|
+
...schema,
|
|
190
|
+
items: schema.items.map((i) => maskWithReference(i, storedSchemas, true))
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
...schema,
|
|
195
|
+
items: maskWithReference(schema.items, storedSchemas, true)
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return schema;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/core/operation-mask.ts
|
|
202
|
+
function maskSchema(storedSchemas, schema) {
|
|
203
|
+
if (!schema) return schema;
|
|
204
|
+
return maskWithReference(schema, storedSchemas, true);
|
|
205
|
+
}
|
|
206
|
+
function maskParameterSchema(param, storedSchemas) {
|
|
207
|
+
if ("$ref" in param) return param;
|
|
208
|
+
return { ...param, schema: maskSchema(storedSchemas, param.schema) };
|
|
209
|
+
}
|
|
210
|
+
function maskContentSchema(storedSchemas, bodyContent) {
|
|
211
|
+
if (!bodyContent) return bodyContent;
|
|
212
|
+
return Object.entries(bodyContent).reduce((collection, [contentType, content]) => ({
|
|
213
|
+
...collection,
|
|
214
|
+
[contentType]: {
|
|
215
|
+
...content,
|
|
216
|
+
schema: maskSchema(storedSchemas, content.schema)
|
|
217
|
+
}
|
|
218
|
+
}), {});
|
|
219
|
+
}
|
|
220
|
+
function maskRequestBodySchema(storedSchemas, body) {
|
|
221
|
+
if (!body || "$ref" in body) return body;
|
|
222
|
+
return { ...body, content: maskContentSchema(storedSchemas, body.content) };
|
|
223
|
+
}
|
|
224
|
+
function maskResponseSchema(storedSchemas, response) {
|
|
225
|
+
if ("$ref" in response) return response;
|
|
226
|
+
return { ...response, content: maskContentSchema(storedSchemas, response.content) };
|
|
227
|
+
}
|
|
228
|
+
function maskSchemasInResponses(storedSchemas, responses) {
|
|
229
|
+
if (!responses) return responses;
|
|
230
|
+
return Object.entries(responses).reduce((collection, [key, response]) => ({
|
|
231
|
+
...collection,
|
|
232
|
+
[key]: maskResponseSchema(storedSchemas, response)
|
|
233
|
+
}), {});
|
|
234
|
+
}
|
|
235
|
+
function maskOperationSchemas(operation, storedSchemas) {
|
|
236
|
+
return {
|
|
237
|
+
...operation,
|
|
238
|
+
parameters: operation.parameters?.map((p) => maskParameterSchema(p, storedSchemas)),
|
|
239
|
+
requestBody: maskRequestBodySchema(storedSchemas, operation.requestBody),
|
|
240
|
+
responses: maskSchemasInResponses(storedSchemas, operation.responses)
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/core/route.ts
|
|
245
|
+
function getRoutePathName(filePath, rootPath) {
|
|
246
|
+
return filePath.replace(rootPath, "").replace("[", "{").replace("]", "}").replaceAll("\\", "/").replace("/route.ts", "");
|
|
247
|
+
}
|
|
248
|
+
function createRouteRecord(method, filePath, rootPath, apiData) {
|
|
249
|
+
return {
|
|
250
|
+
method: method.toLocaleLowerCase(),
|
|
251
|
+
path: getRoutePathName(filePath, rootPath),
|
|
252
|
+
apiData
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function bundlePaths(source, storedSchemas) {
|
|
256
|
+
source.sort((a, b) => a.path.localeCompare(b.path));
|
|
257
|
+
return source.reduce((collection, route) => ({
|
|
258
|
+
...collection,
|
|
259
|
+
[route.path]: {
|
|
260
|
+
...collection[route.path],
|
|
261
|
+
[route.method]: maskOperationSchemas(route.apiData, storedSchemas)
|
|
262
|
+
}
|
|
263
|
+
}), {});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/core/schema.ts
|
|
267
|
+
function bundleSchemas(schemas) {
|
|
268
|
+
const bundledSchemas = Object.keys(schemas).reduce((collection, schemaName) => {
|
|
269
|
+
return {
|
|
270
|
+
...collection,
|
|
271
|
+
[schemaName]: convertToOpenAPI(schemas[schemaName], false)
|
|
272
|
+
};
|
|
273
|
+
}, {});
|
|
274
|
+
return Object.entries(bundledSchemas).reduce((bundle, [schemaName, schema]) => ({
|
|
275
|
+
...bundle,
|
|
276
|
+
[schemaName]: maskWithReference(schema, schemas, false)
|
|
277
|
+
}), {});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/core/generateOpenApiSpec.ts
|
|
281
|
+
async function generateOpenApiSpec(schemas, {
|
|
282
|
+
include: includeOption = [],
|
|
283
|
+
exclude: excludeOption = [],
|
|
284
|
+
routeDefinerName = "defineRoute"
|
|
285
|
+
} = {}) {
|
|
286
|
+
const verifiedOptions = verifyOptions(includeOption, excludeOption);
|
|
287
|
+
const appFolderPath = await findAppFolderPath();
|
|
288
|
+
if (!appFolderPath) throw new Error("This is not a Next.js application!");
|
|
289
|
+
const routes = await getDirectoryItems(appFolderPath, "route.ts");
|
|
290
|
+
const verifiedRoutes = filterDirectoryItems(appFolderPath, routes, verifiedOptions.include, verifiedOptions.exclude);
|
|
291
|
+
const validRoutes = [];
|
|
292
|
+
for (const route of verifiedRoutes) {
|
|
293
|
+
const exportedRouteHandlers = await getRouteExports(route, routeDefinerName, schemas);
|
|
294
|
+
for (const [method, routeHandler] of Object.entries(exportedRouteHandlers)) {
|
|
295
|
+
if (!routeHandler || !routeHandler.apiData) continue;
|
|
296
|
+
validRoutes.push(createRouteRecord(
|
|
297
|
+
method.toLocaleLowerCase(),
|
|
298
|
+
route,
|
|
299
|
+
appFolderPath,
|
|
300
|
+
routeHandler.apiData
|
|
301
|
+
));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const metadata = getPackageMetadata();
|
|
305
|
+
return {
|
|
306
|
+
openapi: "3.1.0",
|
|
307
|
+
info: {
|
|
308
|
+
title: metadata.serviceName,
|
|
309
|
+
version: metadata.version
|
|
310
|
+
},
|
|
311
|
+
paths: bundlePaths(validRoutes, schemas),
|
|
312
|
+
components: {
|
|
313
|
+
schemas: bundleSchemas(schemas)
|
|
314
|
+
},
|
|
315
|
+
tags: []
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/index.ts
|
|
320
|
+
var src_default = generateOpenApiSpec;
|
|
321
|
+
export {
|
|
322
|
+
src_default as default
|
|
323
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omer-x/next-openapi-json-generator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "a Next.js plugin to generate OpenAPI documentation from route handlers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"next.js",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"url": "https://omermecitoglu.github.io"
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
|
+
"type": "module",
|
|
31
32
|
"main": "dist/index.js",
|
|
32
33
|
"types": "dist/index.d.ts",
|
|
33
34
|
"files": [
|
|
@@ -35,9 +36,8 @@
|
|
|
35
36
|
],
|
|
36
37
|
"scripts": {
|
|
37
38
|
"test": "jest",
|
|
38
|
-
"
|
|
39
|
-
"build": "
|
|
40
|
-
"dev": "webpack build --progress --mode=development --watch"
|
|
39
|
+
"dev": "tsup --watch",
|
|
40
|
+
"build": "tsup"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@omer-x/package-metadata": "^0.1.2",
|
|
@@ -49,15 +49,11 @@
|
|
|
49
49
|
"@omer-x/eslint-config": "^1.0.7",
|
|
50
50
|
"@omer-x/openapi-types": "^0.2.1",
|
|
51
51
|
"@types/node": "^22.7.5",
|
|
52
|
-
"clean-webpack-plugin": "^4.0.0",
|
|
53
52
|
"eslint": "^8.57.1",
|
|
54
53
|
"semantic-release": "^24.1.2",
|
|
55
54
|
"ts-jest": "^29.2.5",
|
|
56
|
-
"ts-loader": "^9.5.1",
|
|
57
55
|
"ts-node": "^10.9.2",
|
|
58
|
-
"
|
|
59
|
-
"webpack": "^5.95.0",
|
|
60
|
-
"webpack-cli": "^5.1.4",
|
|
56
|
+
"tsup": "^8.3.0",
|
|
61
57
|
"zod": "^3.23.8"
|
|
62
58
|
},
|
|
63
59
|
"peerDependencies": {
|
package/dist/jest.config.d.ts
DELETED
package/dist/src/core/dir.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export declare function directoryExists(dirPath: string): Promise<boolean>;
|
|
2
|
-
export declare function getDirectoryItems(dirPath: string, targetFileName: string): Promise<string[]>;
|
|
3
|
-
export declare function filterDirectoryItems(rootPath: string, items: string[], include: string[], exclude: string[]): string[];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { OpenApiDocument } from "@omer-x/openapi-types";
|
|
2
|
-
import type { ZodType } from "zod";
|
|
3
|
-
type GeneratorOptions = {
|
|
4
|
-
include?: string[];
|
|
5
|
-
exclude?: string[];
|
|
6
|
-
routeDefinerName?: string;
|
|
7
|
-
};
|
|
8
|
-
export default function generateOpenApiSpec(schemas: Record<string, ZodType>, { include: includeOption, exclude: excludeOption, routeDefinerName, }?: GeneratorOptions): Promise<Omit<OpenApiDocument, "components"> & Required<Pick<OpenApiDocument, "components">>>;
|
|
9
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/src/core/mask.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/src/core/next.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { OperationObject } from "@omer-x/openapi-types/operation";
|
|
2
|
-
export declare function findAppFolderPath(): Promise<string | null>;
|
|
3
|
-
export declare function getRouteExports(routePath: string, routeDefinerName: string, schemas: Record<string, unknown>): Promise<Record<string, {
|
|
4
|
-
apiData?: OperationObject;
|
|
5
|
-
} | undefined>>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/src/core/route.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { OperationObject } from "@omer-x/openapi-types/operation";
|
|
2
|
-
import type { PathsObject } from "@omer-x/openapi-types/paths";
|
|
3
|
-
import type { ZodType } from "zod";
|
|
4
|
-
export type RouteRecord = {
|
|
5
|
-
method: string;
|
|
6
|
-
path: string;
|
|
7
|
-
apiData: OperationObject;
|
|
8
|
-
};
|
|
9
|
-
export declare function createRouteRecord(method: string, filePath: string, rootPath: string, apiData: OperationObject): RouteRecord;
|
|
10
|
-
export declare function bundlePaths(source: RouteRecord[], storedSchemas: Record<string, ZodType>): PathsObject;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function transpile(rawCode: string, routeDefinerName: string): string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/src/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function deepEqual(a: unknown, b: unknown): boolean;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|