xypriss-swagger 1.0.11 → 1.0.13

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/README.md CHANGED
@@ -27,6 +27,9 @@ This module is designed to be loaded natively by the XyPriss plugin manager. Ens
27
27
  }
28
28
  ```
29
29
 
30
+ > [!NOTE]
31
+ > For a deep dive into how XyPriss manages plugin isolation and filesystem access, see the [Workspace System Guide](../core/WORKSPACE_SYSTEM.md).
32
+
30
33
  ## Security & Permissions
31
34
 
32
35
  In order to properly analyze your project's codebase and generate accurate Swagger documentation, this plugin requires the `CWD://` (Current Working Directory) context permission.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/index.ts"],"sourcesContent":["import { logger, Logger } from \"./configs/Logger\";\nimport { meta, toPascalCase } from \"./configs/meta\";\nimport { SwaggerServer } from \"./server\";\nimport { SwaggerConfig } from \"./types\";\nimport { Plugin } from \"xypriss\";\n\n// console.log(\"[swagger] internal plugin sys\", __sys__.__root__);\n\nconst pluginName = toPascalCase(meta.name);\nexport function SwaggerPlugin(config: SwaggerConfig): any {\n return Plugin.create(\n {\n name: meta.name,\n version: meta.version,\n description: meta.description,\n\n onRegister(_error) {\n const log = Logger.for(\"Bootstrap\");\n log.info(\"Starting swagger plugin...\");\n if (_error) {\n log.error(pluginName + \" plugin failed to start:\", _error);\n }\n },\n onServerStart(server) {\n logger.success(pluginName + \" plugin has started\");\n\n server.app.get(\"/swagger\", (_req: any, res: any) => {\n res.redirect(`http://localhost:${config.port}`);\n });\n },\n onAuxiliaryServerDeploy(ops, server) {\n SwaggerServer(config, ops, server);\n },\n },\n __sys__.__root__,\n );\n}\n\n"],"names":["pluginName","toPascalCase","meta","name","config","Plugin","create","version","description","onRegister","_error","log","Logger","for","info","error","onServerStart","server","logger","success","app","get","_req","res","redirect","port","onAuxiliaryServerDeploy","ops","SwaggerServer","__sys__","__root__"],"mappings":"+HAQA,MAAMA,EAAaC,EAAAA,aAAaC,EAAAA,KAAKC,4BAC/B,SAAwBC,GAC1B,OAAOC,EAAAA,OAAOC,OACV,CACIH,KAAMD,EAAAA,KAAKC,KACXI,QAASL,EAAAA,KAAKK,QACdC,YAAaN,EAAAA,KAAKM,YAElB,UAAAC,CAAWC,GACP,MAAMC,EAAMC,EAAAA,OAAOC,IAAI,aACvBF,EAAIG,KAAK,8BACLJ,GACAC,EAAII,MAAMf,EAAa,2BAA4BU,EAE3D,EACA,aAAAM,CAAcC,GACVC,SAAOC,QAAQnB,EAAa,uBAE5BiB,EAAOG,IAAIC,IAAI,WAAY,CAACC,EAAWC,KACnCA,EAAIC,SAAS,oBAAoBpB,EAAOqB,SAEhD,EACA,uBAAAC,CAAwBC,EAAKV,GACzBW,EAAAA,cAAcxB,EAAQuB,EAC1B,GAEJE,QAAQC,SAEhB"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/index.ts"],"sourcesContent":["import { logger, Logger } from \"./configs/Logger\";\nimport { meta, toPascalCase } from \"./configs/meta\";\nimport { SwaggerServer } from \"./server\";\nimport { SwaggerConfig } from \"./types\";\nimport { Plugin } from \"xypriss\";\n\n// console.log(\"[swagger] internal plugin sys\", __sys__.__root__);\n\nconst pluginName = toPascalCase(meta.name);\nexport function SwaggerPlugin(config: SwaggerConfig) {\n return Plugin.create(\n {\n name: meta.name,\n version: meta.version,\n description: meta.description,\n onRegister(_error) {\n const log = Logger.for(\"Bootstrap\");\n log.info(\"Starting swagger plugin...\");\n if (_error) {\n log.error(pluginName + \" plugin failed to start:\", _error);\n }\n },\n onServerStart(server) {\n logger.success(pluginName + \" plugin has started\");\n\n server.app.get(\"/swagger\", (_req: any, res: any) => {\n res.redirect(`http://localhost:${config.port}`);\n });\n },\n onAuxiliaryServerDeploy(ops, server) {\n SwaggerServer(config, ops, server);\n },\n }, \n __sys__.__root__,\n );\n}\n\n"],"names":["pluginName","toPascalCase","meta","name","config","Plugin","create","version","description","onRegister","_error","log","Logger","for","info","error","onServerStart","server","logger","success","app","get","_req","res","redirect","port","onAuxiliaryServerDeploy","ops","SwaggerServer","__sys__","__root__"],"mappings":"+HAQA,MAAMA,EAAaC,EAAAA,aAAaC,EAAAA,KAAKC,4BAC/B,SAAwBC,GAC1B,OAAOC,EAAAA,OAAOC,OACV,CACIH,KAAMD,EAAAA,KAAKC,KACXI,QAASL,EAAAA,KAAKK,QACdC,YAAaN,EAAAA,KAAKM,YAClB,UAAAC,CAAWC,GACP,MAAMC,EAAMC,EAAAA,OAAOC,IAAI,aACvBF,EAAIG,KAAK,8BACLJ,GACAC,EAAII,MAAMf,EAAa,2BAA4BU,EAE3D,EACA,aAAAM,CAAcC,GACVC,SAAOC,QAAQnB,EAAa,uBAE5BiB,EAAOG,IAAIC,IAAI,WAAY,CAACC,EAAWC,KACnCA,EAAIC,SAAS,oBAAoBpB,EAAOqB,SAEhD,EACA,uBAAAC,CAAwBC,EAAKV,GACzBW,EAAAA,cAAcxB,EAAQuB,EAC1B,GAEJE,QAAQC,SAEhB"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("./configs/meta.js");exports.generateOpenAPI=function(t,s){const a={openapi:e.meta.version,info:{title:__sys__.vars.__name__||s.title||"XyPriss API Documentation",version:s.version||"1.0.0",description:s.description||e.meta.description},paths:{},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer"}}}};for(const e of t){if(!e.path||!e.method)continue;const t=e.path.replace(/:([a-zA-Z0-9_]+)(\([^)]+\))?/g,"{$1}");a.paths[t]||(a.paths[t]={});const s=(Array.isArray(e.method)?e.method[0]:e.method).toLowerCase(),r={summary:e.meta?.summary||`${e.method} ${e.path}`,description:e.meta?.description||"",tags:e.meta?.tags||["Default"],parameters:[],responses:e.responses||{200:{description:"Successful response"}}};if(e.hasGuards&&(r.security=[{BearerAuth:[]}]),e.paramNames&&e.paramNames.length>0)for(const t of e.paramNames){const s=e.path.match(new RegExp(`:${t}\\\\(([^)]+)\\\\)`)),a=s?s[1]:void 0;r.parameters.push({name:t,in:"path",required:!0,schema:{type:"string",pattern:a}})}e.meta?.openapi&&Object.assign(r,e.meta.openapi),a.paths[t][s]=r}return a};
1
+ "use strict";var e=require("./configs/meta.js");exports.generateOpenAPI=function(t,s){const a={openapi:e.meta.version,info:{title:__sys__.vars.__name__||s.title||"XyPriss API Documentation",version:s.version||"1.0.0",description:s.description||e.meta.description},paths:{},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer"}}}};for(const e of t){if(!e.path||!e.method)continue;const t=e.path.replace(/:([a-zA-Z0-9_]+)(?:<[^>]+>)?(?:\([^)]+\))?/g,"{$1}");a.paths[t]||(a.paths[t]={});const s=(Array.isArray(e.method)?e.method[0]:e.method).toLowerCase(),r={summary:e.meta?.summary||`${e.method} ${e.path}`,description:e.meta?.description||"",tags:e.meta?.tags||["Default"],parameters:[],responses:e.responses||{200:{description:"Successful response"}}};if(e.hasGuards&&(r.security=[{BearerAuth:[]}]),e.paramNames&&e.paramNames.length>0)for(const t of e.paramNames){const s=e.paramConstraints?.[t];let a,n="string";s&&("number"===s.type||"integer"===s.type?n="number":"boolean"===s.type?n="boolean":"regex"===s.type&&"string"==typeof s.options?a=s.options:"uuid"===s.type&&(a="^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")),r.parameters.push({name:t,in:"path",required:!0,schema:{type:n,pattern:a}})}e.meta?.openapi&&Object.assign(r,e.meta.openapi),a.paths[t][s]=r}return a};
2
2
  //# sourceMappingURL=openapi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.js","sources":["../../../../src/openapi.ts"],"sourcesContent":["import { meta } from \"./configs/meta\";\n\nexport interface OpenAPIConfig {\n openapi: string;\n info: {\n title: string;\n version: string;\n description?: string;\n };\n paths: Record<string, any>;\n components: {\n securitySchemes?: Record<string, any>;\n };\n}\n\nexport function generateOpenAPI(registry: any[], config: any): OpenAPIConfig {\n const doc: OpenAPIConfig = {\n openapi: meta.version,\n info: {\n title:\n __sys__.vars.__name__ ||\n config.title ||\n \"XyPriss API Documentation\",\n version: config.version || \"1.0.0\",\n description: config.description || meta.description,\n },\n paths: {},\n components: {\n securitySchemes: {\n BearerAuth: {\n type: \"http\",\n scheme: \"bearer\",\n },\n },\n },\n };\n\n for (const route of registry) {\n if (!route.path || !route.method) continue;\n\n // Convert Express-like path /users/:id to Swagger-like path /users/{id}\n const openApiPath = route.path.replace(\n /:([a-zA-Z0-9_]+)(\\([^)]+\\))?/g,\n \"{$1}\",\n );\n\n if (!doc.paths[openApiPath]) {\n doc.paths[openApiPath] = {};\n }\n\n const methodStr = (\n Array.isArray(route.method) ? route.method[0] : route.method\n ).toLowerCase();\n\n // Base operation object\n const operation: any = {\n summary: route.meta?.summary || `${route.method} ${route.path}`,\n description: route.meta?.description || \"\",\n tags: route.meta?.tags || [\"Default\"],\n parameters: [],\n responses: route.responses || {\n \"200\": {\n description: \"Successful response\",\n },\n },\n };\n\n // If guards are detected, optionally assume it requires Auth\n if (route.hasGuards) {\n operation.security = [{ BearerAuth: [] }];\n }\n\n // Add Path Parameters\n if (route.paramNames && route.paramNames.length > 0) {\n for (const param of route.paramNames) {\n // Determine if there is a Regex constraint\n const constraintMatch = route.path.match(\n new RegExp(`:${param}\\\\\\\\(([^)]+)\\\\\\\\)`),\n );\n const pattern = constraintMatch\n ? constraintMatch[1]\n : undefined;\n\n operation.parameters.push({\n name: param,\n in: \"path\",\n required: true,\n schema: {\n type: \"string\", // fallback, precise type could depend on regex\n pattern,\n },\n });\n }\n }\n\n // Add additional meta (like requestBody, query params) if defined by user within meta.openapi\n if (route.meta?.openapi) {\n Object.assign(operation, route.meta.openapi);\n }\n\n doc.paths[openApiPath][methodStr] = operation;\n }\n\n return doc;\n}\n\n"],"names":["registry","config","doc","openapi","meta","version","info","title","__sys__","vars","__name__","description","paths","components","securitySchemes","BearerAuth","type","scheme","route","path","method","openApiPath","replace","methodStr","Array","isArray","toLowerCase","operation","summary","tags","parameters","responses","hasGuards","security","paramNames","length","param","constraintMatch","match","RegExp","pattern","undefined","push","name","in","required","schema","Object","assign"],"mappings":"wEAeM,SAA0BA,EAAiBC,GAC7C,MAAMC,EAAqB,CACvBC,QAASC,EAAAA,KAAKC,QACdC,KAAM,CACFC,MACIC,QAAQC,KAAKC,UACbT,EAAOM,OACP,4BACJF,QAASJ,EAAOI,SAAW,QAC3BM,YAAaV,EAAOU,aAAeP,EAAAA,KAAKO,aAE5CC,MAAO,CAAA,EACPC,WAAY,CACRC,gBAAiB,CACbC,WAAY,CACRC,KAAM,OACNC,OAAQ,aAMxB,IAAK,MAAMC,KAASlB,EAAU,CAC1B,IAAKkB,EAAMC,OAASD,EAAME,OAAQ,SAGlC,MAAMC,EAAcH,EAAMC,KAAKG,QAC3B,gCACA,QAGCpB,EAAIU,MAAMS,KACXnB,EAAIU,MAAMS,GAAe,CAAA,GAG7B,MAAME,GACFC,MAAMC,QAAQP,EAAME,QAAUF,EAAME,OAAO,GAAKF,EAAME,QACxDM,cAGIC,EAAiB,CACnBC,QAASV,EAAMd,MAAMwB,SAAW,GAAGV,EAAME,UAAUF,EAAMC,OACzDR,YAAaO,EAAMd,MAAMO,aAAe,GACxCkB,KAAMX,EAAMd,MAAMyB,MAAQ,CAAC,WAC3BC,WAAY,GACZC,UAAWb,EAAMa,WAAa,CAC1B,IAAO,CACHpB,YAAa,yBAWzB,GALIO,EAAMc,YACNL,EAAUM,SAAW,CAAC,CAAElB,WAAY,MAIpCG,EAAMgB,YAAchB,EAAMgB,WAAWC,OAAS,EAC9C,IAAK,MAAMC,KAASlB,EAAMgB,WAAY,CAElC,MAAMG,EAAkBnB,EAAMC,KAAKmB,MAC/B,IAAIC,OAAO,IAAIH,uBAEbI,EAAUH,EACVA,EAAgB,QAChBI,EAENd,EAAUG,WAAWY,KAAK,CACtBC,KAAMP,EACNQ,GAAI,OACJC,UAAU,EACVC,OAAQ,CACJ9B,KAAM,SACNwB,YAGZ,CAIAtB,EAAMd,MAAMD,SACZ4C,OAAOC,OAAOrB,EAAWT,EAAMd,KAAKD,SAGxCD,EAAIU,MAAMS,GAAaE,GAAaI,CACxC,CAEA,OAAOzB,CACX"}
1
+ {"version":3,"file":"openapi.js","sources":["../../../../src/openapi.ts"],"sourcesContent":["import { meta } from \"./configs/meta\";\n\nexport interface OpenAPIConfig {\n openapi: string;\n info: {\n title: string;\n version: string;\n description?: string;\n };\n paths: Record<string, any>;\n components: {\n securitySchemes?: Record<string, any>;\n };\n}\n\nexport function generateOpenAPI(registry: any[], config: any): OpenAPIConfig {\n const doc: OpenAPIConfig = {\n openapi: meta.version,\n info: {\n title:\n __sys__.vars.__name__ ||\n config.title ||\n \"XyPriss API Documentation\",\n version: config.version || \"1.0.0\",\n description: config.description || meta.description,\n },\n paths: {},\n components: {\n securitySchemes: {\n BearerAuth: {\n type: \"http\",\n scheme: \"bearer\",\n },\n },\n },\n };\n\n for (const route of registry) {\n if (!route.path || !route.method) continue;\n\n // Convert Express-like path /users/:id to Swagger-like path /users/{id}\n // Handles: :id, :id<number>, :id(\\d+)\n const openApiPath = route.path.replace(\n /:([a-zA-Z0-9_]+)(?:<[^>]+>)?(?:\\([^)]+\\))?/g,\n \"{$1}\",\n );\n\n if (!doc.paths[openApiPath]) {\n doc.paths[openApiPath] = {};\n }\n\n const methodStr = (\n Array.isArray(route.method) ? route.method[0] : route.method\n ).toLowerCase();\n\n // Base operation object\n const operation: any = {\n summary: route.meta?.summary || `${route.method} ${route.path}`,\n description: route.meta?.description || \"\",\n tags: route.meta?.tags || [\"Default\"],\n parameters: [],\n responses: route.responses || {\n \"200\": {\n description: \"Successful response\",\n },\n },\n };\n\n // If guards are detected, optionally assume it requires Auth\n if (route.hasGuards) {\n operation.security = [{ BearerAuth: [] }];\n }\n\n // Add Path Parameters\n if (route.paramNames && route.paramNames.length > 0) {\n for (const param of route.paramNames) {\n const constraint = route.paramConstraints?.[param];\n let type = \"string\";\n let pattern: string | undefined = undefined;\n\n if (constraint) {\n if (\n constraint.type === \"number\" ||\n constraint.type === \"integer\"\n ) {\n type = \"number\";\n } else if (constraint.type === \"boolean\") {\n type = \"boolean\";\n } else if (\n constraint.type === \"regex\" &&\n typeof constraint.options === \"string\"\n ) {\n pattern = constraint.options;\n } else if (constraint.type === \"uuid\") {\n pattern =\n \"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$\";\n }\n }\n\n operation.parameters.push({\n name: param,\n in: \"path\",\n required: true,\n schema: {\n type,\n pattern,\n },\n });\n }\n }\n\n // Add additional meta (like requestBody, query params) if defined by user within meta.openapi\n if (route.meta?.openapi) {\n Object.assign(operation, route.meta.openapi);\n }\n\n doc.paths[openApiPath][methodStr] = operation;\n }\n\n return doc;\n}\n\n"],"names":["registry","config","doc","openapi","meta","version","info","title","__sys__","vars","__name__","description","paths","components","securitySchemes","BearerAuth","type","scheme","route","path","method","openApiPath","replace","methodStr","Array","isArray","toLowerCase","operation","summary","tags","parameters","responses","hasGuards","security","paramNames","length","param","constraint","paramConstraints","pattern","options","push","name","in","required","schema","Object","assign"],"mappings":"wEAeM,SAA0BA,EAAiBC,GAC7C,MAAMC,EAAqB,CACvBC,QAASC,EAAAA,KAAKC,QACdC,KAAM,CACFC,MACIC,QAAQC,KAAKC,UACbT,EAAOM,OACP,4BACJF,QAASJ,EAAOI,SAAW,QAC3BM,YAAaV,EAAOU,aAAeP,EAAAA,KAAKO,aAE5CC,MAAO,CAAA,EACPC,WAAY,CACRC,gBAAiB,CACbC,WAAY,CACRC,KAAM,OACNC,OAAQ,aAMxB,IAAK,MAAMC,KAASlB,EAAU,CAC1B,IAAKkB,EAAMC,OAASD,EAAME,OAAQ,SAIlC,MAAMC,EAAcH,EAAMC,KAAKG,QAC3B,8CACA,QAGCpB,EAAIU,MAAMS,KACXnB,EAAIU,MAAMS,GAAe,CAAA,GAG7B,MAAME,GACFC,MAAMC,QAAQP,EAAME,QAAUF,EAAME,OAAO,GAAKF,EAAME,QACxDM,cAGIC,EAAiB,CACnBC,QAASV,EAAMd,MAAMwB,SAAW,GAAGV,EAAME,UAAUF,EAAMC,OACzDR,YAAaO,EAAMd,MAAMO,aAAe,GACxCkB,KAAMX,EAAMd,MAAMyB,MAAQ,CAAC,WAC3BC,WAAY,GACZC,UAAWb,EAAMa,WAAa,CAC1B,IAAO,CACHpB,YAAa,yBAWzB,GALIO,EAAMc,YACNL,EAAUM,SAAW,CAAC,CAAElB,WAAY,MAIpCG,EAAMgB,YAAchB,EAAMgB,WAAWC,OAAS,EAC9C,IAAK,MAAMC,KAASlB,EAAMgB,WAAY,CAClC,MAAMG,EAAanB,EAAMoB,mBAAmBF,GAC5C,IACIG,EADAvB,EAAO,SAGPqB,IAEwB,WAApBA,EAAWrB,MACS,YAApBqB,EAAWrB,KAEXA,EAAO,SACoB,YAApBqB,EAAWrB,KAClBA,EAAO,UAEa,UAApBqB,EAAWrB,MACmB,iBAAvBqB,EAAWG,QAElBD,EAAUF,EAAWG,QACM,SAApBH,EAAWrB,OAClBuB,EACI,mEAIZZ,EAAUG,WAAWW,KAAK,CACtBC,KAAMN,EACNO,GAAI,OACJC,UAAU,EACVC,OAAQ,CACJ7B,OACAuB,YAGZ,CAIArB,EAAMd,MAAMD,SACZ2C,OAAOC,OAAOpB,EAAWT,EAAMd,KAAKD,SAGxCD,EAAIU,MAAMS,GAAaE,GAAaI,CACxC,CAEA,OAAOzB,CACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/index.ts"],"sourcesContent":["import { logger, Logger } from \"./configs/Logger\";\nimport { meta, toPascalCase } from \"./configs/meta\";\nimport { SwaggerServer } from \"./server\";\nimport { SwaggerConfig } from \"./types\";\nimport { Plugin } from \"xypriss\";\n\n// console.log(\"[swagger] internal plugin sys\", __sys__.__root__);\n\nconst pluginName = toPascalCase(meta.name);\nexport function SwaggerPlugin(config: SwaggerConfig): any {\n return Plugin.create(\n {\n name: meta.name,\n version: meta.version,\n description: meta.description,\n\n onRegister(_error) {\n const log = Logger.for(\"Bootstrap\");\n log.info(\"Starting swagger plugin...\");\n if (_error) {\n log.error(pluginName + \" plugin failed to start:\", _error);\n }\n },\n onServerStart(server) {\n logger.success(pluginName + \" plugin has started\");\n\n server.app.get(\"/swagger\", (_req: any, res: any) => {\n res.redirect(`http://localhost:${config.port}`);\n });\n },\n onAuxiliaryServerDeploy(ops, server) {\n SwaggerServer(config, ops, server);\n },\n },\n __sys__.__root__,\n );\n}\n\n"],"names":["pluginName","toPascalCase","meta","name","SwaggerPlugin","config","Plugin","create","version","description","onRegister","_error","log","Logger","for","info","error","onServerStart","server","logger","success","app","get","_req","res","redirect","port","onAuxiliaryServerDeploy","ops","SwaggerServer","__sys__","__root__"],"mappings":"iMAQA,MAAMA,EAAaC,EAAaC,EAAKC,MAC/B,SAAUC,EAAcC,GAC1B,OAAOC,EAAOC,OACV,CACIJ,KAAMD,EAAKC,KACXK,QAASN,EAAKM,QACdC,YAAaP,EAAKO,YAElB,UAAAC,CAAWC,GACP,MAAMC,EAAMC,EAAOC,IAAI,aACvBF,EAAIG,KAAK,8BACLJ,GACAC,EAAII,MAAMhB,EAAa,2BAA4BW,EAE3D,EACA,aAAAM,CAAcC,GACVC,EAAOC,QAAQpB,EAAa,uBAE5BkB,EAAOG,IAAIC,IAAI,WAAY,CAACC,EAAWC,KACnCA,EAAIC,SAAS,oBAAoBpB,EAAOqB,SAEhD,EACA,uBAAAC,CAAwBC,EAAKV,GACzBW,EAAcxB,EAAQuB,EAC1B,GAEJE,QAAQC,SAEhB"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/index.ts"],"sourcesContent":["import { logger, Logger } from \"./configs/Logger\";\nimport { meta, toPascalCase } from \"./configs/meta\";\nimport { SwaggerServer } from \"./server\";\nimport { SwaggerConfig } from \"./types\";\nimport { Plugin } from \"xypriss\";\n\n// console.log(\"[swagger] internal plugin sys\", __sys__.__root__);\n\nconst pluginName = toPascalCase(meta.name);\nexport function SwaggerPlugin(config: SwaggerConfig) {\n return Plugin.create(\n {\n name: meta.name,\n version: meta.version,\n description: meta.description,\n onRegister(_error) {\n const log = Logger.for(\"Bootstrap\");\n log.info(\"Starting swagger plugin...\");\n if (_error) {\n log.error(pluginName + \" plugin failed to start:\", _error);\n }\n },\n onServerStart(server) {\n logger.success(pluginName + \" plugin has started\");\n\n server.app.get(\"/swagger\", (_req: any, res: any) => {\n res.redirect(`http://localhost:${config.port}`);\n });\n },\n onAuxiliaryServerDeploy(ops, server) {\n SwaggerServer(config, ops, server);\n },\n }, \n __sys__.__root__,\n );\n}\n\n"],"names":["pluginName","toPascalCase","meta","name","SwaggerPlugin","config","Plugin","create","version","description","onRegister","_error","log","Logger","for","info","error","onServerStart","server","logger","success","app","get","_req","res","redirect","port","onAuxiliaryServerDeploy","ops","SwaggerServer","__sys__","__root__"],"mappings":"iMAQA,MAAMA,EAAaC,EAAaC,EAAKC,MAC/B,SAAUC,EAAcC,GAC1B,OAAOC,EAAOC,OACV,CACIJ,KAAMD,EAAKC,KACXK,QAASN,EAAKM,QACdC,YAAaP,EAAKO,YAClB,UAAAC,CAAWC,GACP,MAAMC,EAAMC,EAAOC,IAAI,aACvBF,EAAIG,KAAK,8BACLJ,GACAC,EAAII,MAAMhB,EAAa,2BAA4BW,EAE3D,EACA,aAAAM,CAAcC,GACVC,EAAOC,QAAQpB,EAAa,uBAE5BkB,EAAOG,IAAIC,IAAI,WAAY,CAACC,EAAWC,KACnCA,EAAIC,SAAS,oBAAoBpB,EAAOqB,SAEhD,EACA,uBAAAC,CAAwBC,EAAKV,GACzBW,EAAcxB,EAAQuB,EAC1B,GAEJE,QAAQC,SAEhB"}
@@ -1,2 +1,2 @@
1
- import{meta as e}from"./configs/meta.js";function t(t,s){const a={openapi:e.version,info:{title:__sys__.vars.__name__||s.title||"XyPriss API Documentation",version:s.version||"1.0.0",description:s.description||e.description},paths:{},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer"}}}};for(const e of t){if(!e.path||!e.method)continue;const t=e.path.replace(/:([a-zA-Z0-9_]+)(\([^)]+\))?/g,"{$1}");a.paths[t]||(a.paths[t]={});const s=(Array.isArray(e.method)?e.method[0]:e.method).toLowerCase(),r={summary:e.meta?.summary||`${e.method} ${e.path}`,description:e.meta?.description||"",tags:e.meta?.tags||["Default"],parameters:[],responses:e.responses||{200:{description:"Successful response"}}};if(e.hasGuards&&(r.security=[{BearerAuth:[]}]),e.paramNames&&e.paramNames.length>0)for(const t of e.paramNames){const s=e.path.match(new RegExp(`:${t}\\\\(([^)]+)\\\\)`)),a=s?s[1]:void 0;r.parameters.push({name:t,in:"path",required:!0,schema:{type:"string",pattern:a}})}e.meta?.openapi&&Object.assign(r,e.meta.openapi),a.paths[t][s]=r}return a}export{t as generateOpenAPI};
1
+ import{meta as e}from"./configs/meta.js";function t(t,s){const a={openapi:e.version,info:{title:__sys__.vars.__name__||s.title||"XyPriss API Documentation",version:s.version||"1.0.0",description:s.description||e.description},paths:{},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer"}}}};for(const e of t){if(!e.path||!e.method)continue;const t=e.path.replace(/:([a-zA-Z0-9_]+)(?:<[^>]+>)?(?:\([^)]+\))?/g,"{$1}");a.paths[t]||(a.paths[t]={});const s=(Array.isArray(e.method)?e.method[0]:e.method).toLowerCase(),r={summary:e.meta?.summary||`${e.method} ${e.path}`,description:e.meta?.description||"",tags:e.meta?.tags||["Default"],parameters:[],responses:e.responses||{200:{description:"Successful response"}}};if(e.hasGuards&&(r.security=[{BearerAuth:[]}]),e.paramNames&&e.paramNames.length>0)for(const t of e.paramNames){const s=e.paramConstraints?.[t];let a,o="string";s&&("number"===s.type||"integer"===s.type?o="number":"boolean"===s.type?o="boolean":"regex"===s.type&&"string"==typeof s.options?a=s.options:"uuid"===s.type&&(a="^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")),r.parameters.push({name:t,in:"path",required:!0,schema:{type:o,pattern:a}})}e.meta?.openapi&&Object.assign(r,e.meta.openapi),a.paths[t][s]=r}return a}export{t as generateOpenAPI};
2
2
  //# sourceMappingURL=openapi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.js","sources":["../../../../src/openapi.ts"],"sourcesContent":["import { meta } from \"./configs/meta\";\n\nexport interface OpenAPIConfig {\n openapi: string;\n info: {\n title: string;\n version: string;\n description?: string;\n };\n paths: Record<string, any>;\n components: {\n securitySchemes?: Record<string, any>;\n };\n}\n\nexport function generateOpenAPI(registry: any[], config: any): OpenAPIConfig {\n const doc: OpenAPIConfig = {\n openapi: meta.version,\n info: {\n title:\n __sys__.vars.__name__ ||\n config.title ||\n \"XyPriss API Documentation\",\n version: config.version || \"1.0.0\",\n description: config.description || meta.description,\n },\n paths: {},\n components: {\n securitySchemes: {\n BearerAuth: {\n type: \"http\",\n scheme: \"bearer\",\n },\n },\n },\n };\n\n for (const route of registry) {\n if (!route.path || !route.method) continue;\n\n // Convert Express-like path /users/:id to Swagger-like path /users/{id}\n const openApiPath = route.path.replace(\n /:([a-zA-Z0-9_]+)(\\([^)]+\\))?/g,\n \"{$1}\",\n );\n\n if (!doc.paths[openApiPath]) {\n doc.paths[openApiPath] = {};\n }\n\n const methodStr = (\n Array.isArray(route.method) ? route.method[0] : route.method\n ).toLowerCase();\n\n // Base operation object\n const operation: any = {\n summary: route.meta?.summary || `${route.method} ${route.path}`,\n description: route.meta?.description || \"\",\n tags: route.meta?.tags || [\"Default\"],\n parameters: [],\n responses: route.responses || {\n \"200\": {\n description: \"Successful response\",\n },\n },\n };\n\n // If guards are detected, optionally assume it requires Auth\n if (route.hasGuards) {\n operation.security = [{ BearerAuth: [] }];\n }\n\n // Add Path Parameters\n if (route.paramNames && route.paramNames.length > 0) {\n for (const param of route.paramNames) {\n // Determine if there is a Regex constraint\n const constraintMatch = route.path.match(\n new RegExp(`:${param}\\\\\\\\(([^)]+)\\\\\\\\)`),\n );\n const pattern = constraintMatch\n ? constraintMatch[1]\n : undefined;\n\n operation.parameters.push({\n name: param,\n in: \"path\",\n required: true,\n schema: {\n type: \"string\", // fallback, precise type could depend on regex\n pattern,\n },\n });\n }\n }\n\n // Add additional meta (like requestBody, query params) if defined by user within meta.openapi\n if (route.meta?.openapi) {\n Object.assign(operation, route.meta.openapi);\n }\n\n doc.paths[openApiPath][methodStr] = operation;\n }\n\n return doc;\n}\n\n"],"names":["generateOpenAPI","registry","config","doc","openapi","meta","version","info","title","__sys__","vars","__name__","description","paths","components","securitySchemes","BearerAuth","type","scheme","route","path","method","openApiPath","replace","methodStr","Array","isArray","toLowerCase","operation","summary","tags","parameters","responses","hasGuards","security","paramNames","length","param","constraintMatch","match","RegExp","pattern","undefined","push","name","in","required","schema","Object","assign"],"mappings":"yCAeM,SAAUA,EAAgBC,EAAiBC,GAC7C,MAAMC,EAAqB,CACvBC,QAASC,EAAKC,QACdC,KAAM,CACFC,MACIC,QAAQC,KAAKC,UACbT,EAAOM,OACP,4BACJF,QAASJ,EAAOI,SAAW,QAC3BM,YAAaV,EAAOU,aAAeP,EAAKO,aAE5CC,MAAO,CAAA,EACPC,WAAY,CACRC,gBAAiB,CACbC,WAAY,CACRC,KAAM,OACNC,OAAQ,aAMxB,IAAK,MAAMC,KAASlB,EAAU,CAC1B,IAAKkB,EAAMC,OAASD,EAAME,OAAQ,SAGlC,MAAMC,EAAcH,EAAMC,KAAKG,QAC3B,gCACA,QAGCpB,EAAIU,MAAMS,KACXnB,EAAIU,MAAMS,GAAe,CAAA,GAG7B,MAAME,GACFC,MAAMC,QAAQP,EAAME,QAAUF,EAAME,OAAO,GAAKF,EAAME,QACxDM,cAGIC,EAAiB,CACnBC,QAASV,EAAMd,MAAMwB,SAAW,GAAGV,EAAME,UAAUF,EAAMC,OACzDR,YAAaO,EAAMd,MAAMO,aAAe,GACxCkB,KAAMX,EAAMd,MAAMyB,MAAQ,CAAC,WAC3BC,WAAY,GACZC,UAAWb,EAAMa,WAAa,CAC1B,IAAO,CACHpB,YAAa,yBAWzB,GALIO,EAAMc,YACNL,EAAUM,SAAW,CAAC,CAAElB,WAAY,MAIpCG,EAAMgB,YAAchB,EAAMgB,WAAWC,OAAS,EAC9C,IAAK,MAAMC,KAASlB,EAAMgB,WAAY,CAElC,MAAMG,EAAkBnB,EAAMC,KAAKmB,MAC/B,IAAIC,OAAO,IAAIH,uBAEbI,EAAUH,EACVA,EAAgB,QAChBI,EAENd,EAAUG,WAAWY,KAAK,CACtBC,KAAMP,EACNQ,GAAI,OACJC,UAAU,EACVC,OAAQ,CACJ9B,KAAM,SACNwB,YAGZ,CAIAtB,EAAMd,MAAMD,SACZ4C,OAAOC,OAAOrB,EAAWT,EAAMd,KAAKD,SAGxCD,EAAIU,MAAMS,GAAaE,GAAaI,CACxC,CAEA,OAAOzB,CACX"}
1
+ {"version":3,"file":"openapi.js","sources":["../../../../src/openapi.ts"],"sourcesContent":["import { meta } from \"./configs/meta\";\n\nexport interface OpenAPIConfig {\n openapi: string;\n info: {\n title: string;\n version: string;\n description?: string;\n };\n paths: Record<string, any>;\n components: {\n securitySchemes?: Record<string, any>;\n };\n}\n\nexport function generateOpenAPI(registry: any[], config: any): OpenAPIConfig {\n const doc: OpenAPIConfig = {\n openapi: meta.version,\n info: {\n title:\n __sys__.vars.__name__ ||\n config.title ||\n \"XyPriss API Documentation\",\n version: config.version || \"1.0.0\",\n description: config.description || meta.description,\n },\n paths: {},\n components: {\n securitySchemes: {\n BearerAuth: {\n type: \"http\",\n scheme: \"bearer\",\n },\n },\n },\n };\n\n for (const route of registry) {\n if (!route.path || !route.method) continue;\n\n // Convert Express-like path /users/:id to Swagger-like path /users/{id}\n // Handles: :id, :id<number>, :id(\\d+)\n const openApiPath = route.path.replace(\n /:([a-zA-Z0-9_]+)(?:<[^>]+>)?(?:\\([^)]+\\))?/g,\n \"{$1}\",\n );\n\n if (!doc.paths[openApiPath]) {\n doc.paths[openApiPath] = {};\n }\n\n const methodStr = (\n Array.isArray(route.method) ? route.method[0] : route.method\n ).toLowerCase();\n\n // Base operation object\n const operation: any = {\n summary: route.meta?.summary || `${route.method} ${route.path}`,\n description: route.meta?.description || \"\",\n tags: route.meta?.tags || [\"Default\"],\n parameters: [],\n responses: route.responses || {\n \"200\": {\n description: \"Successful response\",\n },\n },\n };\n\n // If guards are detected, optionally assume it requires Auth\n if (route.hasGuards) {\n operation.security = [{ BearerAuth: [] }];\n }\n\n // Add Path Parameters\n if (route.paramNames && route.paramNames.length > 0) {\n for (const param of route.paramNames) {\n const constraint = route.paramConstraints?.[param];\n let type = \"string\";\n let pattern: string | undefined = undefined;\n\n if (constraint) {\n if (\n constraint.type === \"number\" ||\n constraint.type === \"integer\"\n ) {\n type = \"number\";\n } else if (constraint.type === \"boolean\") {\n type = \"boolean\";\n } else if (\n constraint.type === \"regex\" &&\n typeof constraint.options === \"string\"\n ) {\n pattern = constraint.options;\n } else if (constraint.type === \"uuid\") {\n pattern =\n \"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$\";\n }\n }\n\n operation.parameters.push({\n name: param,\n in: \"path\",\n required: true,\n schema: {\n type,\n pattern,\n },\n });\n }\n }\n\n // Add additional meta (like requestBody, query params) if defined by user within meta.openapi\n if (route.meta?.openapi) {\n Object.assign(operation, route.meta.openapi);\n }\n\n doc.paths[openApiPath][methodStr] = operation;\n }\n\n return doc;\n}\n\n"],"names":["generateOpenAPI","registry","config","doc","openapi","meta","version","info","title","__sys__","vars","__name__","description","paths","components","securitySchemes","BearerAuth","type","scheme","route","path","method","openApiPath","replace","methodStr","Array","isArray","toLowerCase","operation","summary","tags","parameters","responses","hasGuards","security","paramNames","length","param","constraint","paramConstraints","pattern","options","push","name","in","required","schema","Object","assign"],"mappings":"yCAeM,SAAUA,EAAgBC,EAAiBC,GAC7C,MAAMC,EAAqB,CACvBC,QAASC,EAAKC,QACdC,KAAM,CACFC,MACIC,QAAQC,KAAKC,UACbT,EAAOM,OACP,4BACJF,QAASJ,EAAOI,SAAW,QAC3BM,YAAaV,EAAOU,aAAeP,EAAKO,aAE5CC,MAAO,CAAA,EACPC,WAAY,CACRC,gBAAiB,CACbC,WAAY,CACRC,KAAM,OACNC,OAAQ,aAMxB,IAAK,MAAMC,KAASlB,EAAU,CAC1B,IAAKkB,EAAMC,OAASD,EAAME,OAAQ,SAIlC,MAAMC,EAAcH,EAAMC,KAAKG,QAC3B,8CACA,QAGCpB,EAAIU,MAAMS,KACXnB,EAAIU,MAAMS,GAAe,CAAA,GAG7B,MAAME,GACFC,MAAMC,QAAQP,EAAME,QAAUF,EAAME,OAAO,GAAKF,EAAME,QACxDM,cAGIC,EAAiB,CACnBC,QAASV,EAAMd,MAAMwB,SAAW,GAAGV,EAAME,UAAUF,EAAMC,OACzDR,YAAaO,EAAMd,MAAMO,aAAe,GACxCkB,KAAMX,EAAMd,MAAMyB,MAAQ,CAAC,WAC3BC,WAAY,GACZC,UAAWb,EAAMa,WAAa,CAC1B,IAAO,CACHpB,YAAa,yBAWzB,GALIO,EAAMc,YACNL,EAAUM,SAAW,CAAC,CAAElB,WAAY,MAIpCG,EAAMgB,YAAchB,EAAMgB,WAAWC,OAAS,EAC9C,IAAK,MAAMC,KAASlB,EAAMgB,WAAY,CAClC,MAAMG,EAAanB,EAAMoB,mBAAmBF,GAC5C,IACIG,EADAvB,EAAO,SAGPqB,IAEwB,WAApBA,EAAWrB,MACS,YAApBqB,EAAWrB,KAEXA,EAAO,SACoB,YAApBqB,EAAWrB,KAClBA,EAAO,UAEa,UAApBqB,EAAWrB,MACmB,iBAAvBqB,EAAWG,QAElBD,EAAUF,EAAWG,QACM,SAApBH,EAAWrB,OAClBuB,EACI,mEAIZZ,EAAUG,WAAWW,KAAK,CACtBC,KAAMN,EACNO,GAAI,OACJC,UAAU,EACVC,OAAQ,CACJ7B,OACAuB,YAGZ,CAIArB,EAAMd,MAAMD,SACZ2C,OAAOC,OAAOpB,EAAWT,EAAMd,KAAKD,SAGxCD,EAAIU,MAAMS,GAAaE,GAAaI,CACxC,CAEA,OAAOzB,CACX"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import * as xypriss from 'xypriss';
2
+
1
3
  interface SwaggerConfig {
2
4
  /**
3
5
  * The path where the UI will be served.
@@ -14,6 +16,6 @@ interface SwaggerConfig {
14
16
  port?: number;
15
17
  }
16
18
 
17
- declare function SwaggerPlugin(config: SwaggerConfig): any;
19
+ declare function SwaggerPlugin(config: SwaggerConfig): xypriss.XyPrissPlugin;
18
20
 
19
21
  export { SwaggerPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xypriss-swagger",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Auto-documentation plugin for XyPriss Router V2",
5
5
  "type": "module",
6
6
  "main": "dist/cjs/index.js",
@@ -20,7 +20,6 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "nehoid": "^2.1.4",
23
- "xypriss": "9.6.48-xnb14",
24
23
  "xypriss-security": "^2.1.13"
25
24
  },
26
25
  "devDependencies": {
@@ -34,5 +33,8 @@
34
33
  "rollup-plugin-dts": "^6.4.1",
35
34
  "tslib": "^2.8.1",
36
35
  "typescript": "^5.0.0"
36
+ },
37
+ "peerDependencies": {
38
+ "xypriss": ">=9.6.69"
37
39
  }
38
40
  }
package/src/index.ts CHANGED
@@ -7,13 +7,12 @@ import { Plugin } from "xypriss";
7
7
  // console.log("[swagger] internal plugin sys", __sys__.__root__);
8
8
 
9
9
  const pluginName = toPascalCase(meta.name);
10
- export function SwaggerPlugin(config: SwaggerConfig): any {
10
+ export function SwaggerPlugin(config: SwaggerConfig) {
11
11
  return Plugin.create(
12
12
  {
13
13
  name: meta.name,
14
14
  version: meta.version,
15
15
  description: meta.description,
16
-
17
16
  onRegister(_error) {
18
17
  const log = Logger.for("Bootstrap");
19
18
  log.info("Starting swagger plugin...");
@@ -31,7 +30,7 @@ export function SwaggerPlugin(config: SwaggerConfig): any {
31
30
  onAuxiliaryServerDeploy(ops, server) {
32
31
  SwaggerServer(config, ops, server);
33
32
  },
34
- },
33
+ },
35
34
  __sys__.__root__,
36
35
  );
37
36
  }
package/src/openapi.ts CHANGED
@@ -39,8 +39,9 @@ export function generateOpenAPI(registry: any[], config: any): OpenAPIConfig {
39
39
  if (!route.path || !route.method) continue;
40
40
 
41
41
  // Convert Express-like path /users/:id to Swagger-like path /users/{id}
42
+ // Handles: :id, :id<number>, :id(\d+)
42
43
  const openApiPath = route.path.replace(
43
- /:([a-zA-Z0-9_]+)(\([^)]+\))?/g,
44
+ /:([a-zA-Z0-9_]+)(?:<[^>]+>)?(?:\([^)]+\))?/g,
44
45
  "{$1}",
45
46
  );
46
47
 
@@ -73,20 +74,35 @@ export function generateOpenAPI(registry: any[], config: any): OpenAPIConfig {
73
74
  // Add Path Parameters
74
75
  if (route.paramNames && route.paramNames.length > 0) {
75
76
  for (const param of route.paramNames) {
76
- // Determine if there is a Regex constraint
77
- const constraintMatch = route.path.match(
78
- new RegExp(`:${param}\\\\(([^)]+)\\\\)`),
79
- );
80
- const pattern = constraintMatch
81
- ? constraintMatch[1]
82
- : undefined;
77
+ const constraint = route.paramConstraints?.[param];
78
+ let type = "string";
79
+ let pattern: string | undefined = undefined;
80
+
81
+ if (constraint) {
82
+ if (
83
+ constraint.type === "number" ||
84
+ constraint.type === "integer"
85
+ ) {
86
+ type = "number";
87
+ } else if (constraint.type === "boolean") {
88
+ type = "boolean";
89
+ } else if (
90
+ constraint.type === "regex" &&
91
+ typeof constraint.options === "string"
92
+ ) {
93
+ pattern = constraint.options;
94
+ } else if (constraint.type === "uuid") {
95
+ pattern =
96
+ "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
97
+ }
98
+ }
83
99
 
84
100
  operation.parameters.push({
85
101
  name: param,
86
102
  in: "path",
87
103
  required: true,
88
104
  schema: {
89
- type: "string", // fallback, precise type could depend on regex
105
+ type,
90
106
  pattern,
91
107
  },
92
108
  });