xypriss-swagger 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.log ADDED
File without changes
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ NEHONIX Open Source License (Nehonix OSL (NOSL)) v1.0
2
+
3
+ Copyright (c) 2026 NEHONIX - www.nehonix.com
4
+
5
+ This License governs the use, modification, and distribution of software provided by NEHONIX under its open source projects. NEHONIX is committed to fostering collaborative innovation while strictly protecting its intellectual property rights. Violation of any term of this License will result in immediate termination of all granted rights and may subject the violator to legal action.
6
+
7
+ The full version of this license is available at: https://dll.nehonix.com/licenses/NOSL
8
+
9
+ > **DISCLAIMER OF WARRANTY**
10
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
11
+
12
+ > **LIMITATION OF LIABILITY**
13
+ > IN NO EVENT SHALL NEHONIX BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING FROM THE USE OR INABILITY TO USE THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # XyPriss Swagger Plugin
2
+
3
+ Auto-documentation execution plugin for XyPriss Router V2.
4
+
5
+ ## Features
6
+
7
+ - Provides automated API documentation via Swagger UI.
8
+ - Securely sandboxed within the XyPriss ecosystem.
9
+ - Caller-aware dependency injection with strict route filtering.
10
+
11
+ ## Usage
12
+
13
+ This module is designed to be loaded natively by the XyPriss plugin manager. Ensure that it is authorized in your `xypriss.config.json` inside the `$internal` block.
14
+
15
+ ```json
16
+ {
17
+ "$internal": {
18
+ "xypriss-swagger": {
19
+ "__meta__": {
20
+ "path": "CWD://node_modules/xypriss-swagger"
21
+ },
22
+ "__xfs__": {
23
+ "path": "CWD://."
24
+ }
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Security & Permissions
31
+
32
+ In order to properly analyze your project's codebase and generate accurate Swagger documentation, this plugin requires the `CWD://` (Current Working Directory) context permission.
33
+
34
+ **Why is `CWD://` required?**
35
+ The plugin needs to resolve the active execution directory to dynamically scan your route files, interpret comments, and compile the OpenAPI JSON structure correctly.
36
+
37
+ **Is it safe?**
38
+ Absolutely. While `CWD://` grants broad access to the project root, the XyPriss Swagger plugin is an official, strictly audited core module. It **exclusively** performs safe, read-only operations targeting your router files. It explicitly ignores sensitive system files (e.g., `.env`, credentials) and does not leak or alter your business logic. Your environment remains completely secure.
39
+
40
+ ## License
41
+
42
+ Provided under the Nehonix Open Source License (NOSL) v1.0. Check the included LICENSE file for comprehensive terms.
43
+
@@ -0,0 +1,2 @@
1
+ "use strict";var o=require("./meta.js");const l="",e="",r="",t="",s="",a="",c="",$="",n="",i="",g="",m={info:{icon:"ℹ️ ",color:n,label:"INFO",labelColor:`${""}${t}`},success:{icon:"✅",color:"",label:"OK",labelColor:`${""}${t}`},warn:{icon:"⚠️ ",color:$,label:"WARN",labelColor:`${i}${t}`},error:{icon:"❌",color:"",label:"ERROR",labelColor:`${""}${a}`},debug:{icon:"🐛",color:c,label:"DEBUG",labelColor:`${g}${a}`},http:{icon:"🌐",color:"",label:"HTTP",labelColor:`${""}${a}`},swagger:{icon:"🛡️ ",color:"",label:"SWAGGER",labelColor:`${g}${a}`},db:{icon:"🗄️ ",color:"",label:"DB",labelColor:`${i}${t}`},auth:{icon:"🔐",color:$,label:"AUTH",labelColor:`${i}${t}`}};class b{context;static showTimestamp=!0;constructor(o){this.context=o}static for(o){return new b(o)}static disableTimestamp(){b.showTimestamp=!1}log(o,...t){const a=m[o],$=b.showTimestamp?`${r}${c}${(new Date).toISOString()}${l} `:"",n=`${a.labelColor}${e} ${a.label} ${l}`,i=`${r}${s}[${this.context}]${l}`,[g,...h]=t,u=`${$}${n} ${i} ${a.color}${a.icon} ${String(g)}${l}`,w="error"===o?console.error:"warn"===o?console.warn:console.log;h.length>0?w(u,...h):w(u)}info(...o){this.log("info",...o)}success(...o){this.log("success",...o)}warn(...o){this.log("warn",...o)}error(...o){this.log("error",...o)}debug(...o){this.log("debug",...o)}http(...o){this.log("http",...o)}swagger(...o){this.log("swagger",...o)}db(...o){this.log("db",...o)}auth(...o){this.log("auth",...o)}banner(o){const r=`${s}${"─".repeat(60)}${l}`,t=o.padStart(30+Math.floor(o.length/2)).padEnd(60);console.log(`\n${r}`),console.log(`${e}${n}${t}${l}`),console.log(`${r}\n`)}}const h=b.for(o.meta.name);exports.Logger=b,exports.logger=h;
2
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sources":["../../../../../src/configs/Logger.ts"],"sourcesContent":["import { meta } from \"./meta\";\n\n/**\n * ANSI color codes for terminal output\n */\nconst ANSI = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n\n // Foreground colors\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n gray: \"\\x1b[90m\",\n\n // Bright foreground\n brightRed: \"\\x1b[91m\",\n brightGreen: \"\\x1b[92m\",\n brightYellow: \"\\x1b[93m\",\n brightBlue: \"\\x1b[94m\",\n brightMagenta: \"\\x1b[95m\",\n brightCyan: \"\\x1b[96m\",\n brightWhite: \"\\x1b[97m\",\n\n // Background colors\n bgRed: \"\\x1b[41m\",\n bgGreen: \"\\x1b[42m\",\n bgYellow: \"\\x1b[43m\",\n bgBlue: \"\\x1b[44m\",\n bgMagenta: \"\\x1b[45m\",\n bgCyan: \"\\x1b[46m\",\n} as const;\n\ntype LogLevel =\n | \"info\"\n | \"success\"\n | \"warn\"\n | \"error\"\n | \"debug\"\n | \"http\"\n | \"swagger\"\n | \"db\"\n | \"auth\";\n\ninterface LogConfig {\n icon: string;\n color: string;\n label: string;\n labelColor: string;\n}\n\nconst LOG_CONFIGS: Record<LogLevel, LogConfig> = {\n info: {\n icon: \"ℹ️ \",\n color: ANSI.brightCyan,\n label: \"INFO\",\n labelColor: `${ANSI.bgCyan}${ANSI.black}`,\n },\n success: {\n icon: \"✅\",\n color: ANSI.brightGreen,\n label: \"OK\",\n labelColor: `${ANSI.bgGreen}${ANSI.black}`,\n },\n warn: {\n icon: \"⚠️ \",\n color: ANSI.brightYellow,\n label: \"WARN\",\n labelColor: `${ANSI.bgYellow}${ANSI.black}`,\n },\n error: {\n icon: \"❌\",\n color: ANSI.brightRed,\n label: \"ERROR\",\n labelColor: `${ANSI.bgRed}${ANSI.white}`,\n },\n debug: {\n icon: \"🐛\",\n color: ANSI.gray,\n label: \"DEBUG\",\n labelColor: `${ANSI.bgMagenta}${ANSI.white}`,\n },\n http: {\n icon: \"🌐\",\n color: ANSI.brightBlue,\n label: \"HTTP\",\n labelColor: `${ANSI.bgBlue}${ANSI.white}`,\n },\n swagger: {\n icon: \"🛡️ \",\n color: ANSI.brightMagenta,\n label: \"SWAGGER\",\n labelColor: `${ANSI.bgMagenta}${ANSI.white}`,\n },\n db: {\n icon: \"🗄️ \",\n color: ANSI.yellow,\n label: \"DB\",\n labelColor: `${ANSI.bgYellow}${ANSI.black}`,\n },\n auth: {\n icon: \"🔐\",\n color: ANSI.brightYellow,\n label: \"AUTH\",\n labelColor: `${ANSI.bgYellow}${ANSI.black}`,\n },\n};\n\nexport class Logger {\n private context: string;\n private static showTimestamp = true;\n\n constructor(context: string) {\n this.context = context;\n }\n\n // ─── Static factory ───────────────────────────────────────────────────────\n\n static for(context: string): Logger {\n return new Logger(context);\n }\n\n static disableTimestamp(): void {\n Logger.showTimestamp = false;\n }\n\n // ─── Core log method ──────────────────────────────────────────────────────\n\n private log(level: LogLevel, ...args: unknown[]): void {\n const cfg = LOG_CONFIGS[level];\n const timestamp = Logger.showTimestamp\n ? `${ANSI.dim}${ANSI.gray}${new Date().toISOString()}${ANSI.reset} `\n : \"\";\n const label = `${cfg.labelColor}${ANSI.bold} ${cfg.label} ${ANSI.reset}`;\n const ctx = `${ANSI.dim}${ANSI.cyan}[${this.context}]${ANSI.reset}`;\n\n // First arg gets the level color + icon, rest are passed raw so Node.js\n // pretty-prints objects/arrays/Errors natively (no JSON.stringify needed).\n const [first, ...rest] = args;\n const prefix = `${timestamp}${label} ${ctx} ${cfg.color}${cfg.icon} ${String(first)}${ANSI.reset}`;\n\n const consoleFn =\n level === \"error\"\n ? console.error\n : level === \"warn\"\n ? console.warn\n : console.log;\n\n rest.length > 0 ? consoleFn(prefix, ...rest) : consoleFn(prefix);\n }\n\n // ─── Public methods ───────────────────────────────────────────────────────\n\n info(...args: unknown[]): void {\n this.log(\"info\", ...args);\n }\n\n success(...args: unknown[]): void {\n this.log(\"success\", ...args);\n }\n\n warn(...args: unknown[]): void {\n this.log(\"warn\", ...args);\n }\n\n error(...args: unknown[]): void {\n this.log(\"error\", ...args);\n }\n\n debug(...args: unknown[]): void {\n this.log(\"debug\", ...args);\n }\n\n http(...args: unknown[]): void {\n this.log(\"http\", ...args);\n }\n\n swagger(...args: unknown[]): void {\n this.log(\"swagger\", ...args);\n }\n\n db(...args: unknown[]): void {\n this.log(\"db\", ...args);\n }\n\n auth(...args: unknown[]): void {\n this.log(\"auth\", ...args);\n }\n\n // ─── Convenience: banner / separator ─────────────────────────────────────\n\n banner(title: string): void {\n const line = `${ANSI.cyan}${\"─\".repeat(60)}${ANSI.reset}`;\n const centered = title\n .padStart(30 + Math.floor(title.length / 2))\n .padEnd(60);\n console.log(`\\n${line}`);\n console.log(`${ANSI.bold}${ANSI.brightCyan}${centered}${ANSI.reset}`);\n console.log(`${line}\\n`);\n }\n}\n\n// ─── Default singleton logger ──────────────────────────────────────────────\n\nexport const logger = Logger.for(meta.name);"],"names":["ANSI","LOG_CONFIGS","info","icon","color","label","labelColor","success","warn","error","debug","http","swagger","db","auth","Logger","context","static","constructor","this","disableTimestamp","showTimestamp","log","level","args","cfg","timestamp","Date","toISOString","ctx","first","rest","prefix","String","consoleFn","console","length","banner","title","line","repeat","centered","padStart","Math","floor","padEnd","logger","for","meta","name"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";require("xypriss");const s=__sys__.fs.readJsonSync(__sys__.fs.join(__sys__.__root__,"package.json"));exports.meta=s,exports.toPascalCase=(s,_="-")=>s.split(_).map(s=>s[0].toUpperCase()+s.slice(1)).join(" ");
2
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sources":["../../../../../src/configs/meta.ts"],"sourcesContent":["import \"xypriss\";\nimport { ISwaggerJSONStructure } from \"../types\";\n\nexport const meta = __sys__.fs.readJsonSync(\n __sys__.fs.join(__sys__.__root__, \"package.json\"),\n) as ISwaggerJSONStructure;\n\nexport const toPascalCase = (str: string, spliter = \"-\") =>\n str\n .split(spliter)\n .map((n) => n[0].toUpperCase() + n.slice(1))\n .join(\" \");\n\n"],"names":["meta","__sys__","fs","readJsonSync","join","__root__","str","spliter","split","map","n","toUpperCase","slice"],"mappings":"sCAGaA,EAAOC,QAAQC,GAAGC,aAC3BF,QAAQC,GAAGE,KAAKH,QAAQI,SAAU,qDAGV,CAACC,EAAaC,EAAU,MAChDD,EACKE,MAAMD,GACNE,IAAKC,GAAMA,EAAE,GAAGC,cAAgBD,EAAEE,MAAM,IACxCR,KAAK"}
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("./configs/Logger.js"),r=require("./configs/meta.js"),t=require("./server.js"),g=require("xypriss");exports.SwaggerPlugin=function(i){return g.Plugin.create({name:r.meta.name,version:r.meta.version,description:r.meta.description,onRegister(r){e.Logger.for("Bootstrap").info("Starting swagger plugin...")},onServerStart(r){e.logger.success("Swagger plugin has started"),r.app.get("/swagger",(e,r)=>{r.redirect(`http://localhost:${i.port}`)})},onAuxiliaryServerDeploy(e,r){t.SwaggerServer(i,e)}})};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/index.ts"],"sourcesContent":["import { logger, Logger } from \"./configs/Logger\";\nimport { meta } from \"./configs/meta\";\nimport { SwaggerServer } from \"./server\";\nimport { SwaggerConfig } from \"./types\";\nimport { Plugin } from \"xypriss\";\n\nexport function SwaggerPlugin(config: SwaggerConfig): any {\n return Plugin.create({\n name: meta.name,\n version: meta.version,\n description: meta.description,\n\n onRegister(_server) {\n const log = Logger.for(\"Bootstrap\");\n log.info(\"Starting swagger plugin...\");\n },\n onServerStart(server) {\n logger.success(\"Swagger 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}\n\n"],"names":["config","Plugin","create","name","meta","version","description","onRegister","_server","Logger","for","info","onServerStart","server","logger","success","app","get","_req","res","redirect","port","onAuxiliaryServerDeploy","ops","SwaggerServer"],"mappings":"qJAMM,SAAwBA,GAC1B,OAAOC,EAAAA,OAAOC,OAAO,CACjBC,KAAMC,EAAAA,KAAKD,KACXE,QAASD,EAAAA,KAAKC,QACdC,YAAaF,EAAAA,KAAKE,YAElB,UAAAC,CAAWC,GACKC,EAAAA,OAAOC,IAAI,aACnBC,KAAK,6BACb,EACA,aAAAC,CAAcC,GACVC,EAAAA,OAAOC,QAAQ,8BAEfF,EAAOG,IAAIC,IAAI,WAAY,CAACC,EAAWC,KACnCA,EAAIC,SAAS,oBAAoBpB,EAAOqB,SAEhD,EACA,uBAAAC,CAAwBC,EAAKV,GACzBW,EAAAA,cAAcxB,EAAQuB,EAC1B,GAER"}
@@ -0,0 +1,2 @@
1
+ "use strict";exports.generateOpenAPI=function(e,t){const s={openapi:"3.0.0",info:{title:__sys__.vars.__name__||t.title||"XyPriss API Documentation",version:t.version||"1.0.0",description:t.description||"Generated by @xypriss/swagger"},paths:{},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer"}}}};for(const t of e){if(!t.path||!t.method)continue;const e=t.path.replace(/:([a-zA-Z0-9_]+)(\([^)]+\))?/g,"{$1}");s.paths[e]||(s.paths[e]={});const a=(Array.isArray(t.method)?t.method[0]:t.method).toLowerCase(),r={summary:t.meta?.summary||`${t.method} ${t.path}`,description:t.meta?.description||"",tags:t.meta?.tags||["Default"],parameters:[],responses:{200:{description:"Successful response"}}};if(t.hasGuards&&(r.security=[{BearerAuth:[]}]),t.paramNames&&t.paramNames.length>0)for(const e of t.paramNames){const s=t.path.match(new RegExp(`:${e}\\\\(([^)]+)\\\\)`)),a=s?s[1]:void 0;r.parameters.push({name:e,in:"path",required:!0,schema:{type:"string",pattern:a}})}t.meta?.openapi&&Object.assign(r,t.meta.openapi),s.paths[e][a]=r}return s};
2
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sources":["../../../../src/openapi.ts"],"sourcesContent":["export 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: \"3.0.0\",\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 || \"Generated by @xypriss/swagger\",\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: {\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","info","title","__sys__","vars","__name__","version","description","paths","components","securitySchemes","BearerAuth","type","scheme","route","path","method","openApiPath","replace","methodStr","Array","isArray","toLowerCase","operation","summary","meta","tags","parameters","responses","hasGuards","security","paramNames","length","param","constraintMatch","match","RegExp","pattern","undefined","push","name","in","required","schema","Object","assign"],"mappings":"qCAaM,SAA0BA,EAAiBC,GAC7C,MAAMC,EAAqB,CACvBC,QAAS,QACTC,KAAM,CACFC,MACIC,QAAQC,KAAKC,UACbP,EAAOI,OACP,4BACJI,QAASR,EAAOQ,SAAW,QAC3BC,YAAaT,EAAOS,aAAe,iCAEvCC,MAAO,CAAA,EACPC,WAAY,CACRC,gBAAiB,CACbC,WAAY,CACRC,KAAM,OACNC,OAAQ,aAMxB,IAAK,MAAMC,KAASjB,EAAU,CAC1B,IAAKiB,EAAMC,OAASD,EAAME,OAAQ,SAGlC,MAAMC,EAAcH,EAAMC,KAAKG,QAC3B,gCACA,QAGCnB,EAAIS,MAAMS,KACXlB,EAAIS,MAAMS,GAAe,CAAA,GAG7B,MAAME,GACFC,MAAMC,QAAQP,EAAME,QAAUF,EAAME,OAAO,GAAKF,EAAME,QACxDM,cAGIC,EAAiB,CACnBC,QAASV,EAAMW,MAAMD,SAAW,GAAGV,EAAME,UAAUF,EAAMC,OACzDR,YAAaO,EAAMW,MAAMlB,aAAe,GACxCmB,KAAMZ,EAAMW,MAAMC,MAAQ,CAAC,WAC3BC,WAAY,GACZC,UAAW,CACP,IAAO,CACHrB,YAAa,yBAWzB,GALIO,EAAMe,YACNN,EAAUO,SAAW,CAAC,CAAEnB,WAAY,MAIpCG,EAAMiB,YAAcjB,EAAMiB,WAAWC,OAAS,EAC9C,IAAK,MAAMC,KAASnB,EAAMiB,WAAY,CAElC,MAAMG,EAAkBpB,EAAMC,KAAKoB,MAC/B,IAAIC,OAAO,IAAIH,uBAEbI,EAAUH,EACVA,EAAgB,QAChBI,EAENf,EAAUI,WAAWY,KAAK,CACtBC,KAAMP,EACNQ,GAAI,OACJC,UAAU,EACVC,OAAQ,CACJ/B,KAAM,SACNyB,YAGZ,CAIAvB,EAAMW,MAAMzB,SACZ4C,OAAOC,OAAOtB,EAAWT,EAAMW,KAAKzB,SAGxCD,EAAIS,MAAMS,GAAaE,GAAaI,CACxC,CAEA,OAAOxB,CACX"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("./configs/Logger.js"),o=require("./configs/meta.js"),t=require("./openapi.js"),r=require("./ui.js");exports.SwaggerServer=function(s,n,i){const a=s.path||"/docs",c=`${a}/swagger.json`;console.log("plugin root path: ",__sys__.__root__),console.log("🤠 env from root using __sys__ (devrait être strictement undefined vue que ici, sys.__root__ devrait conduire vers '/home/idevo/Documents/projects/XyPriss/mods/swagger') pourtant le .env de cette root n'a pas de name: ",__sys__.__env__.get("NAME"));const g=__sys__.plugins.get(o.meta.name);if(!g)throw new Error(o.toPascalCase(o.meta.name,"-")+" is not authorized in your xypriss.config.jsonc or xypriss.config.json. Please add ");console.log("🤠 env from root using workspaceSYS (devrait être undefined selon la config de l'utilisateur: en mode ROOT:// ça devrait conduire vers _sys__.root ('/home/idevo/Documents/projects/XyPriss/mods/swagger') et CWD:// devrait envoyer process.cwd() ('/home/idevo/Documents/projects/XyPriss' (vue qu'on excute la cmd ici))): ",g.__env__.get("NAME")),console.log("😝 root path: ",g.__root__),console.log("😅 listing directory path: ",g.fs.ls("."));const _=s.port||7070,l=n.createAuxiliaryServer({server:{port:_},security:{enabled:!1}});l.get(c,(o,r)=>{try{let e=[];n.getRouteRegistry&&(e=n.getRouteRegistry());const o=t.generateOpenAPI(e,s);r.json(o)}catch(o){e.logger.error("Error generating OpenAPI spec:",o),r.status(500).json({error:"Failed to generate documentation"})}}),l.get(a,(e,o)=>{const t=r.getSwaggerUIHtml(c,s.title||g?.vars?.__name__||"API Documentation");o.html(t)}),l.redirect("/",a,301);const u=`http://localhost:${_}${a}`;l.start(()=>{e.logger.swagger(`${o.toPascalCase(o.meta.name)} Server isolated on port ${_}`),e.logger.http(`GET ${u}`)})};
2
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sources":["../../../../src/server.ts"],"sourcesContent":["import { logger } from \"./configs/Logger\";\nimport { meta, toPascalCase } from \"./configs/meta\";\nimport { generateOpenAPI } from \"./openapi\";\nimport { SwaggerConfig } from \"./types\";\nimport { getSwaggerUIHtml } from \"./ui\";\nimport { Plugin } from \"xypriss\";\n// import * as fs from \"fs\";\n\ntype auxis = NonNullable<\n ReturnType<typeof Plugin.create>[\"onAuxiliaryServerDeploy\"]\n>;\nexport type OpsServerManager = Parameters<auxis>[\"0\"] & {\n getRouteRegistry?: () => any[];\n};\nexport type XyPrissServer = Parameters<auxis>[\"1\"];\n\nexport function SwaggerServer(\n config: SwaggerConfig,\n ops: OpsServerManager,\n _XServer: XyPrissServer,\n) {\n const docPath = config.path || \"/docs\";\n const specPath = `${docPath}/swagger.json`;\n console.log(\"plugin root path: \", __sys__.__root__);\n // try {\n // fs.readFileSync(\"fake\");\n // } catch (e) {}\n\n // console.log(\n // \"😇 env de HELLO depuis le plugin: \",\n // __sys__.__env__.get(\"HELLO\"),\n // );\n // console.log(\n // \"🤧 env de COMMON_VAR du root du project (devrait être undefined): \",\n // __sys__.__env__.get(\"COMMON_VAR\"),\n // );\n\n console.log(\n \"🤠 env from root using __sys__ (devrait être strictement undefined vue que ici, sys.__root__ devrait conduire vers '/home/idevo/Documents/projects/XyPriss/mods/swagger') pourtant le .env de cette root n'a pas de name: \",\n __sys__.__env__.get(\"NAME\"),\n );\n\n const workspaceSYS = __sys__.plugins.get(meta.name);\n\n // console.log(\"workspaceFS: \", workspaceFS);\n\n if (!workspaceSYS) {\n throw new Error(\n toPascalCase(meta.name, \"-\") +\n \" is not authorized in your xypriss.config.jsonc or xypriss.config.json. Please add \",\n );\n }\n console.log(\n \"🤠 env from root using workspaceSYS (devrait être undefined selon la config de l'utilisateur: en mode ROOT:// ça devrait conduire vers _sys__.root ('/home/idevo/Documents/projects/XyPriss/mods/swagger') et CWD:// devrait envoyer process.cwd() ('/home/idevo/Documents/projects/XyPriss' (vue qu'on excute la cmd ici))): \",\n workspaceSYS.__env__.get(\"NAME\"),\n );\n console.log(\"😝 root path: \", workspaceSYS.__root__);\n console.log(\"😅 listing directory path: \", workspaceSYS.fs.ls(\".\"));\n\n const port = config.port || 7070;\n const server = ops.createAuxiliaryServer({\n server: { port },\n security: {\n enabled: false,\n },\n });\n\n // Serve the raw OpenAPI JSON specification\n server.get(specPath, (_req, res) => {\n try {\n let registry: any[] = [];\n\n if (ops.getRouteRegistry) {\n registry = ops.getRouteRegistry();\n }\n\n const spec = generateOpenAPI(registry, config);\n res.json(spec);\n } catch (error) {\n logger.error(\"Error generating OpenAPI spec:\", error);\n res.status(500).json({\n error: \"Failed to generate documentation\",\n });\n }\n });\n\n // Serve the Swagger HTML Viewer\n server.get(docPath, (_req, res) => {\n const html = getSwaggerUIHtml(\n specPath,\n config.title || workspaceSYS?.vars?.__name__ || \"API Documentation\",\n );\n res.html(html);\n });\n\n // Redirect root path of the sub-server to docPath\n server.redirect(\"/\", docPath, 301);\n\n // Boot the auxiliary server immediately\n const url = `http://localhost:${port}${docPath}`;\n server.start(() => {\n logger.swagger(\n `${toPascalCase(meta.name)} Server isolated on port ${port}`,\n );\n logger.http(`GET ${url}`);\n });\n}\n\n"],"names":["config","ops","_XServer","docPath","path","specPath","console","log","__sys__","__root__","__env__","get","workspaceSYS","plugins","meta","name","Error","toPascalCase","fs","ls","port","server","createAuxiliaryServer","security","enabled","_req","res","registry","getRouteRegistry","spec","generateOpenAPI","json","error","logger","status","html","getSwaggerUIHtml","title","vars","__name__","redirect","url","start","swagger","http"],"mappings":"+JAiBIA,EACAC,EACAC,GAEA,MAAMC,EAAUH,EAAOI,MAAQ,QACzBC,EAAW,GAAGF,iBACpBG,QAAQC,IAAI,qBAAsBC,QAAQC,UAc1CH,QAAQC,IACJ,6NACAC,QAAQE,QAAQC,IAAI,SAGxB,MAAMC,EAAeJ,QAAQK,QAAQF,IAAIG,EAAAA,KAAKC,MAI9C,IAAKH,EACD,MAAM,IAAII,MACNC,EAAAA,aAAaH,EAAAA,KAAKC,KAAM,KACpB,uFAGZT,QAAQC,IACJ,iUACAK,EAAaF,QAAQC,IAAI,SAE7BL,QAAQC,IAAI,iBAAkBK,EAAaH,UAC3CH,QAAQC,IAAI,8BAA+BK,EAAaM,GAAGC,GAAG,MAE9D,MAAMC,EAAOpB,EAAOoB,MAAQ,KACtBC,EAASpB,EAAIqB,sBAAsB,CACrCD,OAAQ,CAAED,QACVG,SAAU,CACNC,SAAS,KAKjBH,EAAOV,IAAIN,EAAU,CAACoB,EAAMC,KACxB,IACI,IAAIC,EAAkB,GAElB1B,EAAI2B,mBACJD,EAAW1B,EAAI2B,oBAGnB,MAAMC,EAAOC,EAAAA,gBAAgBH,EAAU3B,GACvC0B,EAAIK,KAAKF,EACb,CAAE,MAAOG,GACLC,SAAOD,MAAM,iCAAkCA,GAC/CN,EAAIQ,OAAO,KAAKH,KAAK,CACjBC,MAAO,oCAEf,IAIJX,EAAOV,IAAIR,EAAS,CAACsB,EAAMC,KACvB,MAAMS,EAAOC,mBACT/B,EACAL,EAAOqC,OAASzB,GAAc0B,MAAMC,UAAY,qBAEpDb,EAAIS,KAAKA,KAIbd,EAAOmB,SAAS,IAAKrC,EAAS,KAG9B,MAAMsC,EAAM,oBAAoBrB,IAAOjB,IACvCkB,EAAOqB,MAAM,KACTT,SAAOU,QACH,GAAG1B,eAAaH,EAAAA,KAAKC,iCAAiCK,KAE1Da,EAAAA,OAAOW,KAAK,OAAOH,MAE3B"}
@@ -0,0 +1,381 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{title}} - XyPriss API Docs</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&display=swap"
11
+ rel="stylesheet"
12
+ />
13
+ <style>
14
+ :root {
15
+ --bg: #05070a;
16
+ --surface: #0f1218;
17
+ --surface-hover: #161b22;
18
+ --primary: #6366f1;
19
+ --primary-hover: #818cf8;
20
+ --text: #f1f5f9;
21
+ --text-muted: #94a3b8;
22
+ --border: rgba(255, 255, 255, 0.06);
23
+
24
+ --get: #10b981;
25
+ --post: #3b82f6;
26
+ --put: #f59e0b;
27
+ --delete: #ef4444;
28
+ }
29
+
30
+ * {
31
+ margin: 0;
32
+ padding: 0;
33
+ box-sizing: border-box;
34
+ }
35
+ body {
36
+ font-family: "Outfit", sans-serif;
37
+ background-color: var(--bg);
38
+ color: var(--text);
39
+ display: flex;
40
+ min-height: 100vh;
41
+ }
42
+
43
+ aside {
44
+ width: 320px;
45
+ background-color: var(--surface);
46
+ border-right: 1px solid var(--border);
47
+ padding: 2.5rem 1.5rem;
48
+ position: sticky;
49
+ top: 0;
50
+ height: 100vh;
51
+ display: flex;
52
+ flex-direction: column;
53
+ overflow-y: auto;
54
+ }
55
+
56
+ .logo {
57
+ font-size: 1.25rem;
58
+ font-weight: 700;
59
+ margin-bottom: 2.5rem;
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 0.75rem;
63
+ }
64
+
65
+ .logo-box {
66
+ width: 32px;
67
+ height: 32px;
68
+ background: linear-gradient(135deg, var(--primary), #a855f7);
69
+ border-radius: 8px;
70
+ }
71
+
72
+ .nav-group-title {
73
+ text-transform: uppercase;
74
+ font-size: 0.7rem;
75
+ font-weight: 700;
76
+ letter-spacing: 0.1em;
77
+ color: var(--text-muted);
78
+ margin-bottom: 1rem;
79
+ margin-top: 2rem;
80
+ }
81
+
82
+ .nav-item {
83
+ display: block;
84
+ padding: 0.75rem 1rem;
85
+ border-radius: 8px;
86
+ color: var(--text-muted);
87
+ text-decoration: none;
88
+ font-size: 0.9rem;
89
+ transition: all 0.2s;
90
+ margin-bottom: 0.25rem;
91
+ white-space: nowrap;
92
+ overflow: hidden;
93
+ text-overflow: ellipsis;
94
+ }
95
+
96
+ .nav-item:hover {
97
+ background: var(--surface-hover);
98
+ color: var(--text);
99
+ }
100
+
101
+ .nav-item.active {
102
+ background: rgba(99, 102, 241, 0.1);
103
+ color: var(--primary);
104
+ font-weight: 600;
105
+ }
106
+
107
+ main {
108
+ flex: 1;
109
+ padding: 4rem;
110
+ max-width: 1100px;
111
+ margin: 0 auto;
112
+ }
113
+
114
+ header {
115
+ margin-bottom: 4rem;
116
+ }
117
+
118
+ h1 {
119
+ font-size: 3rem;
120
+ font-weight: 700;
121
+ margin-bottom: 1rem;
122
+ letter-spacing: -0.02em;
123
+ }
124
+
125
+ .description {
126
+ font-size: 1.1rem;
127
+ color: var(--text-muted);
128
+ line-height: 1.7;
129
+ max-width: 800px;
130
+ }
131
+
132
+ .endpoint-section {
133
+ margin-bottom: 4rem;
134
+ scroll-margin-top: 4rem;
135
+ }
136
+
137
+ .endpoint-header {
138
+ display: flex;
139
+ align-items: center;
140
+ gap: 1.5rem;
141
+ margin-bottom: 1.5rem;
142
+ padding-bottom: 1rem;
143
+ border-bottom: 1px solid var(--border);
144
+ }
145
+
146
+ .method-badge {
147
+ padding: 0.4rem 0.8rem;
148
+ border-radius: 6px;
149
+ font-size: 0.8rem;
150
+ font-weight: 700;
151
+ text-transform: uppercase;
152
+ min-width: 70px;
153
+ text-align: center;
154
+ }
155
+
156
+ .method-get {
157
+ background: rgba(16, 185, 129, 0.1);
158
+ color: var(--get);
159
+ border: 1px solid rgba(16, 185, 129, 0.2);
160
+ }
161
+ .method-post {
162
+ background: rgba(59, 130, 246, 0.1);
163
+ color: var(--post);
164
+ border: 1px solid rgba(59, 130, 246, 0.2);
165
+ }
166
+ .method-put {
167
+ background: rgba(245, 158, 11, 0.1);
168
+ color: var(--put);
169
+ border: 1px solid rgba(245, 158, 11, 0.2);
170
+ }
171
+ .method-delete {
172
+ background: rgba(239, 68, 68, 0.1);
173
+ color: var(--delete);
174
+ border: 1px solid rgba(239, 68, 68, 0.2);
175
+ }
176
+
177
+ .path {
178
+ font-family: "Monaco", "Consolas", monospace;
179
+ font-size: 1.1rem;
180
+ font-weight: 600;
181
+ color: var(--text);
182
+ }
183
+
184
+ .endpoint-card {
185
+ background: var(--surface);
186
+ border: 1px solid var(--border);
187
+ border-radius: 16px;
188
+ padding: 2rem;
189
+ margin-top: 1rem;
190
+ }
191
+
192
+ .summary {
193
+ font-size: 1.25rem;
194
+ font-weight: 600;
195
+ margin-bottom: 1rem;
196
+ }
197
+
198
+ .detail-item {
199
+ margin-top: 2rem;
200
+ }
201
+
202
+ .detail-label {
203
+ font-size: 0.8rem;
204
+ font-weight: 700;
205
+ text-transform: uppercase;
206
+ color: var(--text-muted);
207
+ margin-bottom: 0.75rem;
208
+ display: block;
209
+ }
210
+
211
+ .loader {
212
+ display: flex;
213
+ flex-direction: column;
214
+ align-items: center;
215
+ justify-content: center;
216
+ gap: 1.5rem;
217
+ height: 60vh;
218
+ }
219
+
220
+ .spinner {
221
+ width: 40px;
222
+ height: 40px;
223
+ border: 3px solid rgba(99, 102, 241, 0.1);
224
+ border-top-color: var(--primary);
225
+ border-radius: 50%;
226
+ animation: spin 0.8s linear infinite;
227
+ }
228
+
229
+ @keyframes spin {
230
+ to {
231
+ transform: rotate(360deg);
232
+ }
233
+ }
234
+
235
+ #error-view {
236
+ display: none;
237
+ background: rgba(239, 68, 68, 0.05);
238
+ border: 1px solid rgba(239, 68, 68, 0.2);
239
+ padding: 2rem;
240
+ border-radius: 12px;
241
+ color: #ef4444;
242
+ }
243
+ </style>
244
+ </head>
245
+ <body>
246
+ <aside>
247
+ <div class="logo">
248
+ <div class="logo-box"></div>
249
+ XyPriss Docs
250
+ </div>
251
+ <div class="nav-group-title">Endpoints</div>
252
+ <nav id="sidebar-nav">
253
+ <!-- Sidebar links generated dynamically -->
254
+ </nav>
255
+ </aside>
256
+
257
+ <main>
258
+ <div id="loading-view" class="loader">
259
+ <div class="spinner"></div>
260
+ <p style="color: var(--text-muted)">
261
+ Synchronizing with API Core...
262
+ </p>
263
+ </div>
264
+
265
+ <div id="error-view">
266
+ <h3>Failed to load API specification</h3>
267
+ <p id="error-msg"></p>
268
+ </div>
269
+
270
+ <div id="docs-view" style="display: none">
271
+ <header>
272
+ <h1 id="doc-title">{{title}}</h1>
273
+ <p class="description" id="doc-description"></p>
274
+ </header>
275
+
276
+ <div id="endpoints-container">
277
+ <!-- Endpoints generated dynamically -->
278
+ </div>
279
+ </div>
280
+ </main>
281
+
282
+ <script>
283
+ const specUrl = "{{specUrl}}";
284
+ const endpointsContainer = document.getElementById(
285
+ "endpoints-container",
286
+ );
287
+ const sidebarNav = document.getElementById("sidebar-nav");
288
+ const loadingView = document.getElementById("loading-view");
289
+ const docsView = document.getElementById("docs-view");
290
+ const errorView = document.getElementById("error-view");
291
+
292
+ async function init() {
293
+ try {
294
+ const response = await fetch(specUrl);
295
+ if (!response.ok)
296
+ throw new Error(`HTTP Error: ${response.status}`);
297
+ const spec = await response.json();
298
+ render(spec);
299
+ } catch (err) {
300
+ loadingView.style.display = "none";
301
+ errorView.style.display = "block";
302
+ document.getElementById("error-msg").innerText =
303
+ err.message;
304
+ }
305
+ }
306
+
307
+ function render(spec) {
308
+ document.getElementById("doc-title").innerText =
309
+ spec.info.title || "API Documentation";
310
+ document.getElementById("doc-description").innerText =
311
+ spec.info.description || "";
312
+
313
+ const paths = spec.paths || {};
314
+ for (const [path, methods] of Object.entries(paths)) {
315
+ for (const [method, details] of Object.entries(methods)) {
316
+ const id = `${method}-${path.replace(/\//g, "-")}`;
317
+
318
+ // Create Sidebar Link
319
+ const navItem = document.createElement("a");
320
+ navItem.href = `#${id}`;
321
+ navItem.className = "nav-item";
322
+ navItem.innerText = `${method.toUpperCase()} ${path}`;
323
+ sidebarNav.appendChild(navItem);
324
+
325
+ // Create Endpoint Section
326
+ const section = document.createElement("section");
327
+ section.className = "endpoint-section";
328
+ section.id = id;
329
+
330
+ section.innerHTML = `
331
+ <div class="endpoint-header">
332
+ <span class="method-badge method-${method}">${method}</span>
333
+ <span class="path">${path}</span>
334
+ </div>
335
+ <div class="endpoint-card">
336
+ <div class="summary">${details.summary || "No Summary"}</div>
337
+ <p style="color: var(--text-muted)">${details.description || "No description provided."}</p>
338
+
339
+ ${
340
+ details.parameters && details.parameters.length
341
+ ? `
342
+ <div class="detail-item">
343
+ <span class="detail-label">Parameters</span>
344
+ <ul style="list-style: none; color: var(--text-muted)">
345
+ ${details.parameters.map((p) => `<li><code>${p.name}</code> (${p.in})</li>`).join("")}
346
+ </ul>
347
+ </div>
348
+ `
349
+ : ""
350
+ }
351
+
352
+ <div class="detail-item">
353
+ <span class="detail-label">Responses</span>
354
+ <div style="display: flex; gap: 1rem; flex-wrap: wrap;">
355
+ ${Object.entries(details.responses)
356
+ .map(
357
+ ([code, res]) => `
358
+ <div style="background: rgba(255,255,255,0.03); padding: 0.5rem 1rem; border-radius: 8px; border: 1px solid var(--border)">
359
+ <span style="font-weight: 700; color: ${code.startsWith("2") ? "var(--get)" : "var(--delete)"}">${code}</span>
360
+ <span style="font-size: 0.8rem; margin-left: 0.5rem">${res.description}</span>
361
+ </div>
362
+ `,
363
+ )
364
+ .join("")}
365
+ </div>
366
+ </div>
367
+ </div>
368
+ `;
369
+ endpointsContainer.appendChild(section);
370
+ }
371
+ }
372
+
373
+ loadingView.style.display = "none";
374
+ docsView.style.display = "block";
375
+ }
376
+
377
+ init();
378
+ </script>
379
+ </body>
380
+ </html>
381
+
package/dist/cjs/ui.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";exports.getSwaggerUIHtml=function(r,e){const t=require("path").join(__dirname,"..","src","template","ui.html");try{let a=require("fs").readFileSync(t,"utf-8");return a=a.replace(/\{\{title\}\}/g,e),a=a.replace(/\{\{specUrl\}\}/g,r),a}catch(r){return console.error(`[SWAGGER] Error reading UI template at ${t}:`,r),`<h1>Error loading Swagger UI</h1><p>${String(r)}</p>`}};
2
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sources":["../../../../src/ui.ts"],"sourcesContent":["export function getSwaggerUIHtml(specUrl: string, title: string): string {\n const templatePath = require(\"path\").join(\n __dirname,\n \"..\",\n \"src\",\n \"template\",\n \"ui.html\",\n );\n\n try {\n let html = require(\"fs\").readFileSync(templatePath, \"utf-8\");\n\n // Simple template engine using {{}} syntax\n html = html.replace(/\\{\\{title\\}\\}/g, title);\n html = html.replace(/\\{\\{specUrl\\}\\}/g, specUrl);\n\n return html;\n } catch (error) {\n console.error(\n `[SWAGGER] Error reading UI template at ${templatePath}:`,\n error,\n );\n return `<h1>Error loading Swagger UI</h1><p>${String(error)}</p>`;\n }\n}\n\n"],"names":["specUrl","title","templatePath","require","join","__dirname","html","readFileSync","replace","error","console","String"],"mappings":"sCAAM,SAA2BA,EAAiBC,GAC9C,MAAMC,EAAeC,QAAQ,QAAQC,KACjCC,UACA,KACA,MACA,WACA,WAGJ,IACI,IAAIC,EAAOH,QAAQ,MAAMI,aAAaL,EAAc,SAMpD,OAHAI,EAAOA,EAAKE,QAAQ,iBAAkBP,GACtCK,EAAOA,EAAKE,QAAQ,mBAAoBR,GAEjCM,CACX,CAAE,MAAOG,GAKL,OAJAC,QAAQD,MACJ,0CAA0CP,KAC1CO,GAEG,uCAAuCE,OAAOF,QACzD,CACJ"}
@@ -0,0 +1,2 @@
1
+ import{meta as o}from"./meta.js";const l="",e="",r="",t="",a="",s="",$="",c="",n="",i="",m="",b={info:{icon:"ℹ️ ",color:n,label:"INFO",labelColor:`${""}${t}`},success:{icon:"✅",color:"",label:"OK",labelColor:`${""}${t}`},warn:{icon:"⚠️ ",color:c,label:"WARN",labelColor:`${i}${t}`},error:{icon:"❌",color:"",label:"ERROR",labelColor:`${""}${s}`},debug:{icon:"🐛",color:$,label:"DEBUG",labelColor:`${m}${s}`},http:{icon:"🌐",color:"",label:"HTTP",labelColor:`${""}${s}`},swagger:{icon:"🛡️ ",color:"",label:"SWAGGER",labelColor:`${m}${s}`},db:{icon:"🗄️ ",color:"",label:"DB",labelColor:`${i}${t}`},auth:{icon:"🔐",color:c,label:"AUTH",labelColor:`${i}${t}`}};class g{context;static showTimestamp=!0;constructor(o){this.context=o}static for(o){return new g(o)}static disableTimestamp(){g.showTimestamp=!1}log(o,...t){const s=b[o],c=g.showTimestamp?`${r}${$}${(new Date).toISOString()}${l} `:"",n=`${s.labelColor}${e} ${s.label} ${l}`,i=`${r}${a}[${this.context}]${l}`,[m,...h]=t,w=`${c}${n} ${i} ${s.color}${s.icon} ${String(m)}${l}`,p="error"===o?console.error:"warn"===o?console.warn:console.log;h.length>0?p(w,...h):p(w)}info(...o){this.log("info",...o)}success(...o){this.log("success",...o)}warn(...o){this.log("warn",...o)}error(...o){this.log("error",...o)}debug(...o){this.log("debug",...o)}http(...o){this.log("http",...o)}swagger(...o){this.log("swagger",...o)}db(...o){this.log("db",...o)}auth(...o){this.log("auth",...o)}banner(o){const r=`${a}${"─".repeat(60)}${l}`,t=o.padStart(30+Math.floor(o.length/2)).padEnd(60);console.log(`\n${r}`),console.log(`${e}${n}${t}${l}`),console.log(`${r}\n`)}}const h=g.for(o.name);export{g as Logger,h as logger};
2
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sources":["../../../../../src/configs/Logger.ts"],"sourcesContent":["import { meta } from \"./meta\";\n\n/**\n * ANSI color codes for terminal output\n */\nconst ANSI = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n\n // Foreground colors\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n gray: \"\\x1b[90m\",\n\n // Bright foreground\n brightRed: \"\\x1b[91m\",\n brightGreen: \"\\x1b[92m\",\n brightYellow: \"\\x1b[93m\",\n brightBlue: \"\\x1b[94m\",\n brightMagenta: \"\\x1b[95m\",\n brightCyan: \"\\x1b[96m\",\n brightWhite: \"\\x1b[97m\",\n\n // Background colors\n bgRed: \"\\x1b[41m\",\n bgGreen: \"\\x1b[42m\",\n bgYellow: \"\\x1b[43m\",\n bgBlue: \"\\x1b[44m\",\n bgMagenta: \"\\x1b[45m\",\n bgCyan: \"\\x1b[46m\",\n} as const;\n\ntype LogLevel =\n | \"info\"\n | \"success\"\n | \"warn\"\n | \"error\"\n | \"debug\"\n | \"http\"\n | \"swagger\"\n | \"db\"\n | \"auth\";\n\ninterface LogConfig {\n icon: string;\n color: string;\n label: string;\n labelColor: string;\n}\n\nconst LOG_CONFIGS: Record<LogLevel, LogConfig> = {\n info: {\n icon: \"ℹ️ \",\n color: ANSI.brightCyan,\n label: \"INFO\",\n labelColor: `${ANSI.bgCyan}${ANSI.black}`,\n },\n success: {\n icon: \"✅\",\n color: ANSI.brightGreen,\n label: \"OK\",\n labelColor: `${ANSI.bgGreen}${ANSI.black}`,\n },\n warn: {\n icon: \"⚠️ \",\n color: ANSI.brightYellow,\n label: \"WARN\",\n labelColor: `${ANSI.bgYellow}${ANSI.black}`,\n },\n error: {\n icon: \"❌\",\n color: ANSI.brightRed,\n label: \"ERROR\",\n labelColor: `${ANSI.bgRed}${ANSI.white}`,\n },\n debug: {\n icon: \"🐛\",\n color: ANSI.gray,\n label: \"DEBUG\",\n labelColor: `${ANSI.bgMagenta}${ANSI.white}`,\n },\n http: {\n icon: \"🌐\",\n color: ANSI.brightBlue,\n label: \"HTTP\",\n labelColor: `${ANSI.bgBlue}${ANSI.white}`,\n },\n swagger: {\n icon: \"🛡️ \",\n color: ANSI.brightMagenta,\n label: \"SWAGGER\",\n labelColor: `${ANSI.bgMagenta}${ANSI.white}`,\n },\n db: {\n icon: \"🗄️ \",\n color: ANSI.yellow,\n label: \"DB\",\n labelColor: `${ANSI.bgYellow}${ANSI.black}`,\n },\n auth: {\n icon: \"🔐\",\n color: ANSI.brightYellow,\n label: \"AUTH\",\n labelColor: `${ANSI.bgYellow}${ANSI.black}`,\n },\n};\n\nexport class Logger {\n private context: string;\n private static showTimestamp = true;\n\n constructor(context: string) {\n this.context = context;\n }\n\n // ─── Static factory ───────────────────────────────────────────────────────\n\n static for(context: string): Logger {\n return new Logger(context);\n }\n\n static disableTimestamp(): void {\n Logger.showTimestamp = false;\n }\n\n // ─── Core log method ──────────────────────────────────────────────────────\n\n private log(level: LogLevel, ...args: unknown[]): void {\n const cfg = LOG_CONFIGS[level];\n const timestamp = Logger.showTimestamp\n ? `${ANSI.dim}${ANSI.gray}${new Date().toISOString()}${ANSI.reset} `\n : \"\";\n const label = `${cfg.labelColor}${ANSI.bold} ${cfg.label} ${ANSI.reset}`;\n const ctx = `${ANSI.dim}${ANSI.cyan}[${this.context}]${ANSI.reset}`;\n\n // First arg gets the level color + icon, rest are passed raw so Node.js\n // pretty-prints objects/arrays/Errors natively (no JSON.stringify needed).\n const [first, ...rest] = args;\n const prefix = `${timestamp}${label} ${ctx} ${cfg.color}${cfg.icon} ${String(first)}${ANSI.reset}`;\n\n const consoleFn =\n level === \"error\"\n ? console.error\n : level === \"warn\"\n ? console.warn\n : console.log;\n\n rest.length > 0 ? consoleFn(prefix, ...rest) : consoleFn(prefix);\n }\n\n // ─── Public methods ───────────────────────────────────────────────────────\n\n info(...args: unknown[]): void {\n this.log(\"info\", ...args);\n }\n\n success(...args: unknown[]): void {\n this.log(\"success\", ...args);\n }\n\n warn(...args: unknown[]): void {\n this.log(\"warn\", ...args);\n }\n\n error(...args: unknown[]): void {\n this.log(\"error\", ...args);\n }\n\n debug(...args: unknown[]): void {\n this.log(\"debug\", ...args);\n }\n\n http(...args: unknown[]): void {\n this.log(\"http\", ...args);\n }\n\n swagger(...args: unknown[]): void {\n this.log(\"swagger\", ...args);\n }\n\n db(...args: unknown[]): void {\n this.log(\"db\", ...args);\n }\n\n auth(...args: unknown[]): void {\n this.log(\"auth\", ...args);\n }\n\n // ─── Convenience: banner / separator ─────────────────────────────────────\n\n banner(title: string): void {\n const line = `${ANSI.cyan}${\"─\".repeat(60)}${ANSI.reset}`;\n const centered = title\n .padStart(30 + Math.floor(title.length / 2))\n .padEnd(60);\n console.log(`\\n${line}`);\n console.log(`${ANSI.bold}${ANSI.brightCyan}${centered}${ANSI.reset}`);\n console.log(`${line}\\n`);\n }\n}\n\n// ─── Default singleton logger ──────────────────────────────────────────────\n\nexport const logger = Logger.for(meta.name);"],"names":["ANSI","LOG_CONFIGS","info","icon","color","label","labelColor","success","warn","error","debug","http","swagger","db","auth","Logger","context","static","constructor","this","disableTimestamp","showTimestamp","log","level","args","cfg","timestamp","Date","toISOString","ctx","first","rest","prefix","String","consoleFn","console","length","banner","title","line","repeat","centered","padStart","Math","floor","padEnd","logger","for","meta","name"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import"xypriss";const s=__sys__.fs.readJsonSync(__sys__.fs.join(__sys__.__root__,"package.json")),_=(s,_="-")=>s.split(_).map(s=>s[0].toUpperCase()+s.slice(1)).join(" ");export{s as meta,_ as toPascalCase};
2
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sources":["../../../../../src/configs/meta.ts"],"sourcesContent":["import \"xypriss\";\nimport { ISwaggerJSONStructure } from \"../types\";\n\nexport const meta = __sys__.fs.readJsonSync(\n __sys__.fs.join(__sys__.__root__, \"package.json\"),\n) as ISwaggerJSONStructure;\n\nexport const toPascalCase = (str: string, spliter = \"-\") =>\n str\n .split(spliter)\n .map((n) => n[0].toUpperCase() + n.slice(1))\n .join(\" \");\n\n"],"names":["meta","__sys__","fs","readJsonSync","join","__root__","toPascalCase","str","spliter","split","map","n","toUpperCase","slice"],"mappings":"sBAGaA,EAAOC,QAAQC,GAAGC,aAC3BF,QAAQC,GAAGE,KAAKH,QAAQI,SAAU,iBAGzBC,EAAe,CAACC,EAAaC,EAAU,MAChDD,EACKE,MAAMD,GACNE,IAAKC,GAAMA,EAAE,GAAGC,cAAgBD,EAAEE,MAAM,IACxCT,KAAK"}
@@ -0,0 +1,2 @@
1
+ import{logger as r,Logger as e}from"./configs/Logger.js";import{meta as o}from"./configs/meta.js";import{SwaggerServer as t}from"./server.js";import{Plugin as i}from"xypriss";function s(s){return i.create({name:o.name,version:o.version,description:o.description,onRegister(r){e.for("Bootstrap").info("Starting swagger plugin...")},onServerStart(e){r.success("Swagger plugin has started"),e.app.get("/swagger",(r,e)=>{e.redirect(`http://localhost:${s.port}`)})},onAuxiliaryServerDeploy(r,e){t(s,r)}})}export{s as SwaggerPlugin};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/index.ts"],"sourcesContent":["import { logger, Logger } from \"./configs/Logger\";\nimport { meta } from \"./configs/meta\";\nimport { SwaggerServer } from \"./server\";\nimport { SwaggerConfig } from \"./types\";\nimport { Plugin } from \"xypriss\";\n\nexport function SwaggerPlugin(config: SwaggerConfig): any {\n return Plugin.create({\n name: meta.name,\n version: meta.version,\n description: meta.description,\n\n onRegister(_server) {\n const log = Logger.for(\"Bootstrap\");\n log.info(\"Starting swagger plugin...\");\n },\n onServerStart(server) {\n logger.success(\"Swagger 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}\n\n"],"names":["SwaggerPlugin","config","Plugin","create","name","meta","version","description","onRegister","_server","Logger","for","info","onServerStart","server","logger","success","app","get","_req","res","redirect","port","onAuxiliaryServerDeploy","ops","SwaggerServer"],"mappings":"+KAMM,SAAUA,EAAcC,GAC1B,OAAOC,EAAOC,OAAO,CACjBC,KAAMC,EAAKD,KACXE,QAASD,EAAKC,QACdC,YAAaF,EAAKE,YAElB,UAAAC,CAAWC,GACKC,EAAOC,IAAI,aACnBC,KAAK,6BACb,EACA,aAAAC,CAAcC,GACVC,EAAOC,QAAQ,8BAEfF,EAAOG,IAAIC,IAAI,WAAY,CAACC,EAAWC,KACnCA,EAAIC,SAAS,oBAAoBpB,EAAOqB,SAEhD,EACA,uBAAAC,CAAwBC,EAAKV,GACzBW,EAAcxB,EAAQuB,EAC1B,GAER"}
@@ -0,0 +1,2 @@
1
+ function e(e,t){const a={openapi:"3.0.0",info:{title:__sys__.vars.__name__||t.title||"XyPriss API Documentation",version:t.version||"1.0.0",description:t.description||"Generated by @xypriss/swagger"},paths:{},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer"}}}};for(const t of e){if(!t.path||!t.method)continue;const e=t.path.replace(/:([a-zA-Z0-9_]+)(\([^)]+\))?/g,"{$1}");a.paths[e]||(a.paths[e]={});const s=(Array.isArray(t.method)?t.method[0]:t.method).toLowerCase(),r={summary:t.meta?.summary||`${t.method} ${t.path}`,description:t.meta?.description||"",tags:t.meta?.tags||["Default"],parameters:[],responses:{200:{description:"Successful response"}}};if(t.hasGuards&&(r.security=[{BearerAuth:[]}]),t.paramNames&&t.paramNames.length>0)for(const e of t.paramNames){const a=t.path.match(new RegExp(`:${e}\\\\(([^)]+)\\\\)`)),s=a?a[1]:void 0;r.parameters.push({name:e,in:"path",required:!0,schema:{type:"string",pattern:s}})}t.meta?.openapi&&Object.assign(r,t.meta.openapi),a.paths[e][s]=r}return a}export{e as generateOpenAPI};
2
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sources":["../../../../src/openapi.ts"],"sourcesContent":["export 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: \"3.0.0\",\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 || \"Generated by @xypriss/swagger\",\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: {\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","info","title","__sys__","vars","__name__","version","description","paths","components","securitySchemes","BearerAuth","type","scheme","route","path","method","openApiPath","replace","methodStr","Array","isArray","toLowerCase","operation","summary","meta","tags","parameters","responses","hasGuards","security","paramNames","length","param","constraintMatch","match","RegExp","pattern","undefined","push","name","in","required","schema","Object","assign"],"mappings":"AAaM,SAAUA,EAAgBC,EAAiBC,GAC7C,MAAMC,EAAqB,CACvBC,QAAS,QACTC,KAAM,CACFC,MACIC,QAAQC,KAAKC,UACbP,EAAOI,OACP,4BACJI,QAASR,EAAOQ,SAAW,QAC3BC,YAAaT,EAAOS,aAAe,iCAEvCC,MAAO,CAAA,EACPC,WAAY,CACRC,gBAAiB,CACbC,WAAY,CACRC,KAAM,OACNC,OAAQ,aAMxB,IAAK,MAAMC,KAASjB,EAAU,CAC1B,IAAKiB,EAAMC,OAASD,EAAME,OAAQ,SAGlC,MAAMC,EAAcH,EAAMC,KAAKG,QAC3B,gCACA,QAGCnB,EAAIS,MAAMS,KACXlB,EAAIS,MAAMS,GAAe,CAAA,GAG7B,MAAME,GACFC,MAAMC,QAAQP,EAAME,QAAUF,EAAME,OAAO,GAAKF,EAAME,QACxDM,cAGIC,EAAiB,CACnBC,QAASV,EAAMW,MAAMD,SAAW,GAAGV,EAAME,UAAUF,EAAMC,OACzDR,YAAaO,EAAMW,MAAMlB,aAAe,GACxCmB,KAAMZ,EAAMW,MAAMC,MAAQ,CAAC,WAC3BC,WAAY,GACZC,UAAW,CACP,IAAO,CACHrB,YAAa,yBAWzB,GALIO,EAAMe,YACNN,EAAUO,SAAW,CAAC,CAAEnB,WAAY,MAIpCG,EAAMiB,YAAcjB,EAAMiB,WAAWC,OAAS,EAC9C,IAAK,MAAMC,KAASnB,EAAMiB,WAAY,CAElC,MAAMG,EAAkBpB,EAAMC,KAAKoB,MAC/B,IAAIC,OAAO,IAAIH,uBAEbI,EAAUH,EACVA,EAAgB,QAChBI,EAENf,EAAUI,WAAWY,KAAK,CACtBC,KAAMP,EACNQ,GAAI,OACJC,UAAU,EACVC,OAAQ,CACJ/B,KAAM,SACNyB,YAGZ,CAIAvB,EAAMW,MAAMzB,SACZ4C,OAAOC,OAAOtB,EAAWT,EAAMW,KAAKzB,SAGxCD,EAAIS,MAAMS,GAAaE,GAAaI,CACxC,CAEA,OAAOxB,CACX"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }