moonflower 1.5.4 → 1.6.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.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("crypto"),U=require("fs"),W=require("path"),K=require("url"),S=require("ts-morph"),y=require("../../utils/logger.cjs"),R=require("../discoveryModule/discoverImports/discoverImports.cjs"),_=require("../discoveryModule/discoverRouterFiles/discoverRouterFiles.cjs"),H=require("../discoveryModule/discoverRouters/discoverRouters.cjs"),D=require("../manager/OpenApiManager.cjs"),B=require("./getSourceFileTimestamp.cjs"),A=require("./nodeParsers.cjs"),V=require("./parseEndpoint.cjs"),C=require("./parseExposedModels.cjs"),w=require("./sourceFileCache.cjs"),Y=require("./workerPool.cjs");var P=typeof document<"u"?document.currentScript:null;function G(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const l in r)if(l!=="default"){const c=Object.getOwnPropertyDescriptor(r,l);Object.defineProperty(t,l,c.get?c:{enumerable:!0,get:()=>r[l]})}}return t.default=r,Object.freeze(t)}const M=G(W);function J(){const r=["./analyzerWorker.mjs","./analyzerWorker.test.mjs"];for(const t of r){const l=new URL(t,typeof document>"u"?require("url").pathToFileURL(__filename).href:P&&P.tagName.toUpperCase()==="SCRIPT"&&P.src||new URL("openapi/analyzerModule/analyzerModule.cjs",document.baseURI).href);if(U.existsSync(K.fileURLToPath(l)))return l}throw new Error("analyzerWorker.mjs not found. Run yarn build, or run tests via yarn test (which compiles the worker first).")}const Q=2,X=async({logLevel:r,tsconfigPath:t,sourceFilePaths:l,sourceFileDiscovery:c,incremental:p,profiling:m="stats",workers:o=!1})=>{const a=D.OpenApiManager.getInstance();if(a.isReady())return;r&&y.Logger.setLevel(r),y.Logger.info("Preparing OpenAPI spec");const h=new S.Project({tsConfigFilePath:M.resolve(t),skipFileDependencyResolution:!0}),{explicitRouters:g,discoveredRouterFiles:x,allSourceFiles:T}=(()=>{const u=(l??[]).map(f=>M.resolve(f)).map(f=>h.getSourceFileOrThrow(f)),k=u.flatMap(f=>({fileName:f.getFilePath(),sourceFile:f,routers:H.discoverRouters(f)})),{discoveredRouterFiles:b,discoveredSourceFiles:j}=(()=>{if(c===!1)return{discoveredRouterFiles:[],discoveredSourceFiles:[]};const f=performance.now(),E=_.discoverRouterFiles({targetPath:typeof c=="object"?c.rootPath:".",tsConfigPath:t});return m!=="off"&&y.Logger.info(`File discovery took ${Math.round(performance.now()-f)}ms`),E})(),z=u.reduce((f,E)=>f.some(q=>q.getFilePath()===E.getFilePath())?f:f.concat(E),j);return{explicitRouters:k,discoveredRouterFiles:b,allSourceFiles:z}})(),e=g.reduce((i,N)=>i.some(u=>u.fileName===N.fileName)?i:i.concat(N),x),n=T.flatMap(i=>O(i)).filter(i=>!!i);n.length>0&&n[0]&&a.setHeader(n[0]);const s=T.flatMap(i=>$(i));a.setExposedModels(s);const d=typeof p=="object"&&p.cachePath?p.cachePath:M.resolve(process.cwd(),"node_modules",".cache","moonflower"),F=await L(e,{incremental:p!==!1,cachePath:d,timestampCache:{},profiling:m,tsconfigPath:M.resolve(t),workers:o});a.setStats({discoveredRouterFiles:x.map(i=>({path:i.fileName,routers:i.routers.named.map(N=>({name:N,endpoints:F.filter(u=>u.sourceFilePath===i.fileName).map(u=>`${u.method.toUpperCase()} ${u.path}`)}))})),explicitRouterFiles:g.map(i=>({path:i.fileName,routers:i.routers.named.map(N=>({name:N,endpoints:F.filter(u=>u.sourceFilePath===i.fileName).map(u=>`${u.method.toUpperCase()} ${u.path}`)}))}))}),a.setEndpoints(F),a.markAsReady()},L=async(r,t,l)=>{const c=t.profiling??"stats",p=performance.now(),m=[],o=[],a=performance.now(),h=new Map;for(const e of r){const n=B.getSourceFileTimestamp(e.sourceFile,t.timestampCache,h),s=t.incremental?w.SourceFileCache.getCachedResults(e.sourceFile,n,t.cachePath):null;s?(y.Logger.debug(`[${e.fileName}] Found cached results`),m.push({endpoints:s.endpoints,fileName:e.fileName,timing:0,endpointTimings:[]})):o.push({file:e,timestamp:n})}if(c!=="off"&&y.Logger.info(`Cache freshness check took ${Math.round(performance.now()-a)}ms`),o.length===0)return c!=="off"&&y.Logger.info(`Router analysis took ${Math.round(performance.now()-p)}ms`),m.flatMap(e=>e.endpoints);const g=new Map;for(const{file:e}of o)g.set(e.fileName,{endpoints:[],fileName:e.fileName,timing:0,endpointTimings:[]});if(!(t.workers!==!1)||o.length<=Q)for(const{file:e}of o){const{endpoints:n,endpointTimings:s}=v(e),d=g.get(e.fileName);d.endpoints=n,d.endpointTimings=s,d.timing=s.reduce((F,i)=>F+i.timing,0)}else{const e=o.map(({file:d})=>({fileName:d.fileName,task:{taskId:I.randomUUID(),tsconfigPath:t.tsconfigPath,sourceFilePath:d.sourceFile.getFilePath(),routerNames:d.routers.named,filterEndpointPaths:l}})),n=new Y.WorkerPool(J(),e.length);let s;try{s=await n.runAll(e.map(d=>d.task))}finally{n.terminate()}for(let d=0;d<s.length;d++){const F=s[d],i=e[d].fileName,N=g.get(i);if("error"in F){y.Logger.error(`[${i}] Worker error: ${F.error}`);continue}N.endpoints=F.endpoints,N.endpointTimings=F.endpointTimings,N.timing=F.endpointTimings.reduce((u,k)=>u+k.timing,0)}}for(const{file:e,timestamp:n}of o){const s=g.get(e.fileName);s.endpoints.length>0&&w.SourceFileCache.cacheResults(e.sourceFile,n,t.cachePath,s.endpoints)}const T=[...m,...Array.from(g.values())];return c!=="off"&&y.Logger.info(`Router analysis took ${Math.round(performance.now()-p)}ms`),c==="stats"?T.map(e=>({fileName:e.fileName,timeTaken:e.timing})).sort((e,n)=>n.timeTaken-e.timeTaken).filter(e=>e.timeTaken>500).forEach(e=>{y.Logger.info(`- [${e.fileName}] Took ${Math.round(e.timeTaken)}ms to analyze`)}):c==="debug"&&T.map(e=>({fileName:e.fileName,timeTaken:e.timing,endpointTimings:e.endpointTimings})).sort((e,n)=>n.timeTaken-e.timeTaken).forEach(e=>{y.Logger.info(`- [${e.fileName}] Took ${Math.round(e.timeTaken)}ms to analyze`),e.endpointTimings.sort((n,s)=>s.timing-n.timing).forEach(n=>{y.Logger.info(` - ${n.method} ${n.path} (${Math.round(n.timing)}ms)`),n.sectionTimings.filter(s=>s.timing>=1).sort((s,d)=>d.timing-s.timing).forEach(s=>{y.Logger.info(` - ${s.section}: ${Math.round(s.timing)}ms`)})})}),T.flatMap(e=>e.endpoints)},v=(r,t)=>{const l=[],c=[],m=["get","post","put","delete","del","patch"].join("|");return r.routers.named.forEach(o=>{const a=new RegExp(`${o}\\.(?:${m})`);r.sourceFile.forEachChild(h=>{const g=h.getText();if(a.test(g)){A.resolveEndpointPath(h);const x=performance.now(),{endpoint:T,sectionTimings:e}=V.parseEndpoint(h,r.fileName);c.push({method:T.method,path:T.path,timing:performance.now()-x,sectionTimings:e}),l.push(T)}})}),{endpoints:l,endpointTimings:c}},O=r=>{const t=R.discoverImportedName({sourceFile:r,originalName:"useApiHeader"});if(!t)return null;const l=r.forEachChildAsArray().filter(o=>o.isKind(S.SyntaxKind.ExpressionStatement)).find(o=>t&&o.getText().startsWith(t));if(!l)return null;const c=l.getFirstDescendantByKindOrThrow(S.SyntaxKind.ObjectLiteralExpression),p=A.getValuesOfObjectLiteral(c),m=o=>typeof o=="string"||Array.isArray(o)&&o.every(a=>typeof a=="string")?o:o.reduce((a,h)=>typeof h=="string"?a:{...a,[h.identifier]:m(h.value)},{});return m(p)},$=r=>{const t=[],l=R.discoverImportedName({sourceFile:r,originalName:"useExposeApiModel"}),c=R.discoverImportedName({sourceFile:r,originalName:"useExposeNamedApiModels"});return r.forEachChildAsArray().filter(p=>p.isKind(S.SyntaxKind.ExpressionStatement)).map(p=>{if(l&&p.getText().startsWith(l)){const a=(p.getFirstChild()?.getChildrenOfKind(S.SyntaxKind.SyntaxList)||[])[0].getFirstChild();if(!a)return;t.push(C.parseExposedModel(a));return}if(c&&p.getText().startsWith(c)){const a=(p.getFirstChild()?.getChildrenOfKind(S.SyntaxKind.SyntaxList)||[])[0].getFirstChild();if(!a)return;C.parseNamedExposedModels(a).forEach(g=>t.push(g))}}),t};exports.analyzeMultipleSourceFiles=L;exports.analyzeSourceFileApiHeader=O;exports.analyzeSourceFileEndpoints=v;exports.analyzeSourceFileExposedModels=$;exports.prepareOpenApiSpec=X;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("crypto"),U=require("fs"),W=require("path"),K=require("url"),S=require("ts-morph"),y=require("../../utils/logger.cjs"),R=require("../discoveryModule/discoverImports/discoverImports.cjs"),_=require("../discoveryModule/discoverRouterFiles/discoverRouterFiles.cjs"),H=require("../discoveryModule/discoverRouters/discoverRouters.cjs"),D=require("../manager/OpenApiManager.cjs"),B=require("./getSourceFileTimestamp.cjs"),A=require("./nodeParsers.cjs"),V=require("./parseEndpoint.cjs"),C=require("./parseExposedModels.cjs"),w=require("./sourceFileCache.cjs"),Y=require("./workerPool.cjs");var P=typeof document<"u"?document.currentScript:null;function G(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const l in r)if(l!=="default"){const c=Object.getOwnPropertyDescriptor(r,l);Object.defineProperty(t,l,c.get?c:{enumerable:!0,get:()=>r[l]})}}return t.default=r,Object.freeze(t)}const M=G(W);function J(){const r=["./analyzerWorker.mjs","./analyzerWorker.test.mjs"];for(const t of r){const l=new URL(t,typeof document>"u"?require("url").pathToFileURL(__filename).href:P&&P.tagName.toUpperCase()==="SCRIPT"&&P.src||new URL("openapi/analyzerModule/analyzerModule.cjs",document.baseURI).href);if(U.existsSync(K.fileURLToPath(l)))return l}throw new Error("analyzerWorker.mjs not found. Run yarn build, or run tests via yarn test (which compiles the worker first).")}const Q=2,X=async({logLevel:r,tsconfigPath:t,sourceFilePaths:l,sourceFileDiscovery:c,incremental:p,profiling:m="stats",workers:o=!1})=>{const a=D.OpenApiManager.getInstance();if(a.isReady())return;r&&y.Logger.setLevel(r),y.Logger.info("Preparing OpenAPI spec");const f=new S.Project({tsConfigFilePath:M.resolve(t),skipFileDependencyResolution:!0}),{explicitRouters:g,discoveredRouterFiles:x,allSourceFiles:T}=(()=>{const u=(l??[]).map(h=>M.resolve(h)).map(h=>f.getSourceFileOrThrow(h)),k=u.flatMap(h=>({fileName:h.getFilePath(),sourceFile:h,routers:H.discoverRouters(h)})),{discoveredRouterFiles:b,discoveredSourceFiles:j}=(()=>{if(c===!1)return{discoveredRouterFiles:[],discoveredSourceFiles:[]};const h=performance.now(),E=_.discoverRouterFiles({targetPath:typeof c=="object"?c.rootPath:".",project:f});return m!=="off"&&y.Logger.info(`File discovery took ${Math.round(performance.now()-h)}ms`),E})(),z=u.reduce((h,E)=>h.some(q=>q.getFilePath()===E.getFilePath())?h:h.concat(E),j);return{explicitRouters:k,discoveredRouterFiles:b,allSourceFiles:z}})(),e=g.reduce((i,N)=>i.some(u=>u.fileName===N.fileName)?i:i.concat(N),x),n=T.flatMap(i=>O(i)).filter(i=>!!i);n.length>0&&n[0]&&a.setHeader(n[0]);const s=T.flatMap(i=>$(i));a.setExposedModels(s);const d=typeof p=="object"&&p.cachePath?p.cachePath:M.resolve(process.cwd(),"node_modules",".cache","moonflower"),F=await L(e,{incremental:p!==!1,cachePath:d,timestampCache:{},profiling:m,tsconfigPath:M.resolve(t),workers:o});a.setStats({discoveredRouterFiles:x.map(i=>({path:i.fileName,routers:i.routers.named.map(N=>({name:N,endpoints:F.filter(u=>u.sourceFilePath===i.fileName).map(u=>`${u.method.toUpperCase()} ${u.path}`)}))})),explicitRouterFiles:g.map(i=>({path:i.fileName,routers:i.routers.named.map(N=>({name:N,endpoints:F.filter(u=>u.sourceFilePath===i.fileName).map(u=>`${u.method.toUpperCase()} ${u.path}`)}))}))}),a.setEndpoints(F),a.markAsReady()},L=async(r,t,l)=>{const c=t.profiling??"stats",p=performance.now(),m=[],o=[],a=performance.now(),f=new Map;for(const e of r){const n=B.getSourceFileTimestamp(e.sourceFile,t.timestampCache,f),s=t.incremental?w.SourceFileCache.getCachedResults(e.sourceFile,n,t.cachePath):null;s?(y.Logger.debug(`[${e.fileName}] Found cached results`),m.push({endpoints:s.endpoints,fileName:e.fileName,timing:0,endpointTimings:[]})):o.push({file:e,timestamp:n})}if(c!=="off"&&y.Logger.info(`Cache freshness check took ${Math.round(performance.now()-a)}ms`),o.length===0)return c!=="off"&&y.Logger.info(`Router analysis took ${Math.round(performance.now()-p)}ms`),m.flatMap(e=>e.endpoints);const g=new Map;for(const{file:e}of o)g.set(e.fileName,{endpoints:[],fileName:e.fileName,timing:0,endpointTimings:[]});if(!(t.workers!==!1)||o.length<=Q)for(const{file:e}of o){const{endpoints:n,endpointTimings:s}=v(e),d=g.get(e.fileName);d.endpoints=n,d.endpointTimings=s,d.timing=s.reduce((F,i)=>F+i.timing,0)}else{const e=o.map(({file:d})=>({fileName:d.fileName,task:{taskId:I.randomUUID(),tsconfigPath:t.tsconfigPath,sourceFilePath:d.sourceFile.getFilePath(),routerNames:d.routers.named,filterEndpointPaths:l}})),n=new Y.WorkerPool(J(),e.length);let s;try{s=await n.runAll(e.map(d=>d.task))}finally{n.terminate()}for(let d=0;d<s.length;d++){const F=s[d],i=e[d].fileName,N=g.get(i);if("error"in F){y.Logger.error(`[${i}] Worker error: ${F.error}`);continue}N.endpoints=F.endpoints,N.endpointTimings=F.endpointTimings,N.timing=F.endpointTimings.reduce((u,k)=>u+k.timing,0)}}for(const{file:e,timestamp:n}of o){const s=g.get(e.fileName);s.endpoints.length>0&&w.SourceFileCache.cacheResults(e.sourceFile,n,t.cachePath,s.endpoints)}const T=[...m,...Array.from(g.values())];return c!=="off"&&y.Logger.info(`Router analysis took ${Math.round(performance.now()-p)}ms`),c==="stats"?T.map(e=>({fileName:e.fileName,timeTaken:e.timing})).sort((e,n)=>n.timeTaken-e.timeTaken).filter(e=>e.timeTaken>500).forEach(e=>{y.Logger.info(`- [${e.fileName}] Took ${Math.round(e.timeTaken)}ms to analyze`)}):c==="debug"&&T.map(e=>({fileName:e.fileName,timeTaken:e.timing,endpointTimings:e.endpointTimings})).sort((e,n)=>n.timeTaken-e.timeTaken).forEach(e=>{y.Logger.info(`- [${e.fileName}] Took ${Math.round(e.timeTaken)}ms to analyze`),e.endpointTimings.sort((n,s)=>s.timing-n.timing).forEach(n=>{y.Logger.info(` - ${n.method} ${n.path} (${Math.round(n.timing)}ms)`),n.sectionTimings.filter(s=>s.timing>=1).sort((s,d)=>d.timing-s.timing).forEach(s=>{y.Logger.info(` - ${s.section}: ${Math.round(s.timing)}ms`)})})}),T.flatMap(e=>e.endpoints)},v=(r,t)=>{const l=[],c=[],m=["get","post","put","delete","del","patch"].join("|");return r.routers.named.forEach(o=>{const a=new RegExp(`${o}\\.(?:${m})`);r.sourceFile.forEachChild(f=>{const g=f.getText();if(a.test(g)){A.resolveEndpointPath(f);const x=performance.now(),{endpoint:T,sectionTimings:e}=V.parseEndpoint(f,r.fileName);c.push({method:T.method,path:T.path,timing:performance.now()-x,sectionTimings:e}),l.push(T)}})}),{endpoints:l,endpointTimings:c}},O=r=>{const t=R.discoverImportedName({sourceFile:r,originalName:"useApiHeader"});if(!t)return null;const l=r.forEachChildAsArray().filter(o=>o.isKind(S.SyntaxKind.ExpressionStatement)).find(o=>t&&o.getText().startsWith(t));if(!l)return null;const c=l.getFirstDescendantByKindOrThrow(S.SyntaxKind.ObjectLiteralExpression),p=A.getValuesOfObjectLiteral(c),m=o=>typeof o=="string"||Array.isArray(o)&&o.every(a=>typeof a=="string")?o:o.reduce((a,f)=>typeof f=="string"?a:{...a,[f.identifier]:m(f.value)},{});return m(p)},$=r=>{const t=[],l=R.discoverImportedName({sourceFile:r,originalName:"useExposeApiModel"}),c=R.discoverImportedName({sourceFile:r,originalName:"useExposeNamedApiModels"});return r.forEachChildAsArray().filter(p=>p.isKind(S.SyntaxKind.ExpressionStatement)).map(p=>{if(l&&p.getText().startsWith(l)){const a=(p.getFirstChild()?.getChildrenOfKind(S.SyntaxKind.SyntaxList)||[])[0].getFirstChild();if(!a)return;t.push(C.parseExposedModel(a));return}if(c&&p.getText().startsWith(c)){const a=(p.getFirstChild()?.getChildrenOfKind(S.SyntaxKind.SyntaxList)||[])[0].getFirstChild();if(!a)return;C.parseNamedExposedModels(a).forEach(g=>t.push(g))}}),t};exports.analyzeMultipleSourceFiles=L;exports.analyzeSourceFileApiHeader=O;exports.analyzeSourceFileEndpoints=v;exports.analyzeSourceFileExposedModels=$;exports.prepareOpenApiSpec=X;
2
2
  //# sourceMappingURL=analyzerModule.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyzerModule.cjs","sources":["../../../src/openapi/analyzerModule/analyzerModule.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { existsSync } from 'fs'\nimport * as path from 'path'\nimport { fileURLToPath } from 'url'\n\nfunction resolveWorkerUrl(): URL {\n\tconst candidates = ['./analyzerWorker.mjs', './analyzerWorker.test.mjs']\n\tfor (const candidate of candidates) {\n\t\tconst url = new URL(candidate, import.meta.url)\n\t\tif (existsSync(fileURLToPath(url))) {\n\t\t\treturn url\n\t\t}\n\t}\n\tthrow new Error(\n\t\t'analyzerWorker.mjs not found. Run yarn build, or run tests via yarn test (which compiles the worker first).',\n\t)\n}\nimport { SourceFile, SyntaxKind } from 'ts-morph'\nimport { Project } from 'ts-morph'\n\nimport { Logger } from '../../utils/logger'\nimport { discoverImportedName } from '../discoveryModule/discoverImports/discoverImports'\nimport {\n\tDiscoveredSourceFile,\n\tdiscoverRouterFiles,\n} from '../discoveryModule/discoverRouterFiles/discoverRouterFiles'\nimport { discoverRouters } from '../discoveryModule/discoverRouters/discoverRouters'\nimport { ApiDocsHeader, OpenApiManager } from '../manager/OpenApiManager'\nimport { EndpointData, ExposedModelData } from '../types'\nimport { getSourceFileTimestamp, MtimeCache, TimestampCache } from './getSourceFileTimestamp'\nimport { getValuesOfObjectLiteral, resolveEndpointPath } from './nodeParsers'\nimport { parseEndpoint, SectionTiming } from './parseEndpoint'\nimport { parseExposedModel, parseNamedExposedModels } from './parseExposedModels'\nimport { SourceFileCache } from './sourceFileCache'\nimport { WorkerPool, WorkerResult, WorkerTask } from './workerPool'\n\ntype Props = {\n\tlogLevel?: Parameters<(typeof Logger)['setLevel']>[0]\n\ttsconfigPath: string\n\tsourceFilePaths?: string[]\n\tsourceFileDiscovery?: boolean | FileDiscoveryConfig\n\tincremental?:\n\t\t| boolean\n\t\t| {\n\t\t\t\tcachePath: string\n\t\t }\n\tprofiling?: 'stats' | 'off' | 'debug'\n\tworkers?: boolean\n}\n\ntype FileDiscoveryConfig = {\n\trootPath: string\n}\n\ntype EndpointTiming = { method: string; path: string; timing: number; sectionTimings: SectionTiming[] }\n\n/**\n * Number of uncached files at or below which analysis runs inline on the (already-warm) main-thread\n * Project instead of fanning out to worker threads. Each worker pays a multi-second cold-start to\n * build its own Project, so parallelism only wins once there are several files to share that cost.\n */\nconst INLINE_ANALYSIS_FILE_THRESHOLD = 2\n\n/**\n * @param tsconfigPath Path to tsconfig file relative to project root\n * @param sourceFilePaths Array of router source files relative to project root\n */\nexport const prepareOpenApiSpec = async ({\n\tlogLevel,\n\ttsconfigPath,\n\tsourceFilePaths,\n\tsourceFileDiscovery,\n\tincremental,\n\tprofiling = 'stats',\n\tworkers = false,\n}: Props): Promise<void> => {\n\tconst openApiManager = OpenApiManager.getInstance()\n\n\tif (openApiManager.isReady()) {\n\t\treturn\n\t}\n\n\tif (logLevel) {\n\t\tLogger.setLevel(logLevel)\n\t}\n\n\tLogger.info('Preparing OpenAPI spec')\n\n\tconst project = new Project({\n\t\ttsConfigFilePath: path.resolve(tsconfigPath),\n\t\tskipFileDependencyResolution: true,\n\t})\n\n\tconst { explicitRouters, discoveredRouterFiles, allSourceFiles } = (() => {\n\t\tconst sourceFilesToAdd = sourceFilePaths ?? []\n\t\tconst resolvedSourceFilePaths = sourceFilesToAdd.map((filepath) => path.resolve(filepath))\n\t\tconst sourceFiles = resolvedSourceFilePaths.map((filePath) => project.getSourceFileOrThrow(filePath))\n\t\tconst explicitRouters = sourceFiles.flatMap((file) => ({\n\t\t\tfileName: file.getFilePath(),\n\t\t\tsourceFile: file,\n\t\t\trouters: discoverRouters(file),\n\t\t}))\n\n\t\tconst { discoveredRouterFiles, discoveredSourceFiles } = (() => {\n\t\t\tif (sourceFileDiscovery === false) {\n\t\t\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t\t\t}\n\n\t\t\tconst startTime = performance.now()\n\t\t\tconst files = discoverRouterFiles({\n\t\t\t\ttargetPath: typeof sourceFileDiscovery === 'object' ? sourceFileDiscovery.rootPath : '.',\n\t\t\t\ttsConfigPath: tsconfigPath,\n\t\t\t})\n\t\t\tif (profiling !== 'off') {\n\t\t\t\tLogger.info(`File discovery took ${Math.round(performance.now() - startTime)}ms`)\n\t\t\t}\n\t\t\treturn files\n\t\t})()\n\n\t\tconst allSourceFiles = sourceFiles.reduce(\n\t\t\t(acc, current) =>\n\t\t\t\tacc.some((r) => r.getFilePath() === current.getFilePath()) ? acc : acc.concat(current),\n\t\t\tdiscoveredSourceFiles,\n\t\t)\n\n\t\treturn { explicitRouters, discoveredRouterFiles, allSourceFiles }\n\t})()\n\n\tconst filesToAnalyze = explicitRouters.reduce(\n\t\t(acc, current) => (acc.some((r) => r.fileName === current.fileName) ? acc : acc.concat(current)),\n\t\tdiscoveredRouterFiles,\n\t)\n\n\tconst apiHeaders = allSourceFiles\n\t\t.flatMap((file) => analyzeSourceFileApiHeader(file))\n\t\t.filter((headers) => !!headers)\n\tif (apiHeaders.length > 0 && apiHeaders[0]) {\n\t\topenApiManager.setHeader(apiHeaders[0])\n\t}\n\n\tconst exposedModels = allSourceFiles.flatMap((file) => analyzeSourceFileExposedModels(file))\n\n\topenApiManager.setExposedModels(exposedModels)\n\n\tconst cachePath = (() => {\n\t\tif (typeof incremental === 'object' && incremental.cachePath) {\n\t\t\treturn incremental.cachePath\n\t\t}\n\t\treturn path.resolve(process.cwd(), 'node_modules', '.cache', 'moonflower')\n\t})()\n\tconst endpoints = await analyzeMultipleSourceFiles(filesToAnalyze, {\n\t\tincremental: incremental !== false,\n\t\tcachePath,\n\t\ttimestampCache: {},\n\t\tprofiling,\n\t\ttsconfigPath: path.resolve(tsconfigPath),\n\t\tworkers,\n\t})\n\n\topenApiManager.setStats({\n\t\tdiscoveredRouterFiles: discoveredRouterFiles.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t\texplicitRouterFiles: explicitRouters.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t})\n\n\topenApiManager.setEndpoints(endpoints)\n\topenApiManager.markAsReady()\n}\n\nexport const analyzeMultipleSourceFiles = async (\n\tfiles: DiscoveredSourceFile[],\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t\ttsconfigPath: string\n\t\tworkers?: boolean\n\t},\n\tfilterEndpointPaths?: string[],\n): Promise<EndpointData[]> => {\n\tconst profiling = config.profiling ?? 'stats'\n\tconst startTime = performance.now()\n\n\t// Separate cached files from those needing analysis\n\ttype CachedFile = { endpoints: EndpointData[]; fileName: string; timing: 0; endpointTimings: [] }\n\ttype UncachedFile = { file: DiscoveredSourceFile; timestamp: number }\n\n\tconst cached: CachedFile[] = []\n\tconst uncached: UncachedFile[] = []\n\n\tconst freshnessCheckStart = performance.now()\n\tconst mtimeCache: MtimeCache = new Map()\n\tfor (const file of files) {\n\t\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache, mtimeCache)\n\t\tconst hit = config.incremental\n\t\t\t? SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\t\t\t: null\n\t\tif (hit) {\n\t\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\t\tcached.push({ endpoints: hit.endpoints, fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t\t} else {\n\t\t\tuncached.push({ file, timestamp })\n\t\t}\n\t}\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Cache freshness check took ${Math.round(performance.now() - freshnessCheckStart)}ms`)\n\t}\n\n\tif (uncached.length === 0) {\n\t\tif (profiling !== 'off') {\n\t\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t\t}\n\t\treturn cached.flatMap((f) => f.endpoints)\n\t}\n\n\ttype FileResult = {\n\t\tendpoints: EndpointData[]\n\t\tfileName: string\n\t\ttiming: number\n\t\tendpointTimings: EndpointTiming[]\n\t}\n\n\tconst byFile = new Map<string, FileResult>()\n\tfor (const { file } of uncached) {\n\t\tbyFile.set(file.fileName, { endpoints: [], fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t}\n\n\tconst useWorkers = config.workers !== false\n\tif (!useWorkers || uncached.length <= INLINE_ANALYSIS_FILE_THRESHOLD) {\n\t\tfor (const { file } of uncached) {\n\t\t\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\t\t\tconst fileResult = byFile.get(file.fileName)!\n\t\t\tfileResult.endpoints = endpoints\n\t\t\tfileResult.endpointTimings = endpointTimings\n\t\t\tfileResult.timing = endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t} else {\n\t\ttype FileTask = { task: WorkerTask; fileName: string }\n\t\tconst allTasks: FileTask[] = uncached.map(({ file }) => ({\n\t\t\tfileName: file.fileName,\n\t\t\ttask: {\n\t\t\t\ttaskId: crypto.randomUUID(),\n\t\t\t\ttsconfigPath: config.tsconfigPath,\n\t\t\t\tsourceFilePath: file.sourceFile.getFilePath(),\n\t\t\t\trouterNames: file.routers.named,\n\t\t\t\tfilterEndpointPaths,\n\t\t\t},\n\t\t}))\n\n\t\tconst pool = new WorkerPool(resolveWorkerUrl(), allTasks.length)\n\t\tlet results: WorkerResult[]\n\t\ttry {\n\t\t\tresults = await pool.runAll(allTasks.map((ft) => ft.task))\n\t\t} finally {\n\t\t\tpool.terminate()\n\t\t}\n\n\t\t// Each result maps 1:1 to a file task.\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst result = results[i]\n\t\t\tconst fileName = allTasks[i].fileName\n\t\t\tconst fileResult = byFile.get(fileName)!\n\n\t\t\tif ('error' in result) {\n\t\t\t\tLogger.error(`[${fileName}] Worker error: ${result.error}`)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfileResult.endpoints = result.endpoints\n\t\t\tfileResult.endpointTimings = result.endpointTimings\n\t\t\tfileResult.timing = result.endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t}\n\n\t// Write cache for each uncached file\n\tfor (const { file, timestamp } of uncached) {\n\t\tconst fileResult = byFile.get(file.fileName)!\n\t\tif (fileResult.endpoints.length > 0) {\n\t\t\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, fileResult.endpoints)\n\t\t}\n\t}\n\n\tconst analyzedFiles = [...cached, ...Array.from(byFile.values())]\n\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t}\n\n\tif (profiling === 'stats') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.filter((t) => t.timeTaken > 500)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t})\n\t} else if (profiling === 'debug') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing, endpointTimings: f.endpointTimings }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t\tt.endpointTimings\n\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t.forEach((ep) => {\n\t\t\t\t\t\tLogger.info(` - ${ep.method} ${ep.path} (${Math.round(ep.timing)}ms)`)\n\t\t\t\t\t\tep.sectionTimings\n\t\t\t\t\t\t\t.filter((s) => s.timing >= 1)\n\t\t\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t\t\t.forEach((s) => {\n\t\t\t\t\t\t\t\tLogger.info(` - ${s.section}: ${Math.round(s.timing)}ms`)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t})\n\t}\n\n\treturn analyzedFiles.flatMap((f) => f.endpoints)\n}\n\nexport const analyzeSourceFileWithCache = (\n\tfile: DiscoveredSourceFile,\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t},\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; timing: number; endpointTimings: EndpointTiming[] } => {\n\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache)\n\tconst cachedResults = SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\n\tif (cachedResults) {\n\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\treturn { endpoints: cachedResults.endpoints, timing: 0, endpointTimings: [] }\n\t}\n\tLogger.debug(`[${file.fileName}] Analyzing...`)\n\n\tconst t1 = performance.now()\n\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\tconst t2 = performance.now()\n\tLogger.debug(`[${file.fileName}] Analyzed in ${t2 - t1}ms`)\n\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, endpoints)\n\treturn { endpoints, timing: t2 - t1, endpointTimings }\n}\n\nexport const analyzeSourceFileEndpoints = (\n\tfile: DiscoveredSourceFile,\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; endpointTimings: EndpointTiming[] } => {\n\tconst endpoints: EndpointData[] = []\n\tconst endpointTimings: EndpointTiming[] = []\n\tconst operations = ['get', 'post', 'put', 'delete', 'del', 'patch']\n\tconst joinedOperations = operations.join('|')\n\n\tfile.routers.named.forEach((routerName) => {\n\t\tconst routerPattern = new RegExp(`${routerName}\\\\.(?:${joinedOperations})`)\n\t\tfile.sourceFile.forEachChild((node) => {\n\t\t\tconst nodeText = node.getText()\n\n\t\t\tif (routerPattern.test(nodeText)) {\n\t\t\t\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\t\t\t\tif (filterEndpointPaths && !filterEndpointPaths.some((path) => endpointPath.includes(path))) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst t1 = performance.now()\n\t\t\t\tconst { endpoint, sectionTimings } = parseEndpoint(node, file.fileName)\n\t\t\t\tendpointTimings.push({\n\t\t\t\t\tmethod: endpoint.method,\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\ttiming: performance.now() - t1,\n\t\t\t\t\tsectionTimings,\n\t\t\t\t})\n\t\t\t\tendpoints.push(endpoint)\n\t\t\t}\n\t\t})\n\t})\n\n\treturn { endpoints, endpointTimings }\n}\n\nexport const analyzeSourceFileApiHeader = (sourceFile: SourceFile): ApiDocsHeader | null => {\n\tconst nameOfUseApiHeader = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useApiHeader',\n\t})\n\n\tif (!nameOfUseApiHeader) {\n\t\treturn null\n\t}\n\n\tconst node = sourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.find((node) => nameOfUseApiHeader && node.getText().startsWith(nameOfUseApiHeader))\n\n\tif (!node) {\n\t\treturn null\n\t}\n\n\tconst targetNode = node.getFirstDescendantByKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\tconst values = getValuesOfObjectLiteral(targetNode)\n\n\tconst collapseObject = (v: string | string[] | typeof values): any => {\n\t\tif (typeof v === 'string') {\n\t\t\treturn v\n\t\t}\n\t\tif (Array.isArray(v) && v.every((value) => typeof value === 'string')) {\n\t\t\treturn v\n\t\t}\n\n\t\treturn v.reduce((acc, current) => {\n\t\t\tif (typeof current === 'string') {\n\t\t\t\treturn acc\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[current.identifier]: collapseObject(current.value as string[]),\n\t\t\t}\n\t\t}, {})\n\t}\n\treturn collapseObject(values)\n}\n\nexport const analyzeSourceFileExposedModels = (sourceFile: SourceFile): ExposedModelData[] => {\n\tconst models: ExposedModelData[] = []\n\n\tconst nameOfUseExposeApiModel = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeApiModel',\n\t})\n\n\tconst nameOfUseExposeNamedApiModels = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeNamedApiModels',\n\t})\n\n\tsourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.map((node) => {\n\t\t\tif (nameOfUseExposeApiModel && node.getText().startsWith(nameOfUseExposeApiModel)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tmodels.push(parseExposedModel(firstChild))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (nameOfUseExposeNamedApiModels && node.getText().startsWith(nameOfUseExposeNamedApiModels)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst parsedModels = parseNamedExposedModels(firstChild)\n\t\t\t\tparsedModels.forEach((model) => models.push(model))\n\t\t\t}\n\t\t})\n\treturn models\n}\n"],"names":["resolveWorkerUrl","candidates","candidate","url","_documentCurrentScript","existsSync","fileURLToPath","INLINE_ANALYSIS_FILE_THRESHOLD","prepareOpenApiSpec","logLevel","tsconfigPath","sourceFilePaths","sourceFileDiscovery","incremental","profiling","workers","openApiManager","OpenApiManager","Logger","project","Project","path","explicitRouters","discoveredRouterFiles","allSourceFiles","sourceFiles","filepath","filePath","file","discoverRouters","discoveredSourceFiles","startTime","files","discoverRouterFiles","acc","current","r","filesToAnalyze","apiHeaders","analyzeSourceFileApiHeader","headers","exposedModels","analyzeSourceFileExposedModels","cachePath","endpoints","analyzeMultipleSourceFiles","e","config","filterEndpointPaths","cached","uncached","freshnessCheckStart","mtimeCache","timestamp","getSourceFileTimestamp","hit","SourceFileCache","f","byFile","endpointTimings","analyzeSourceFileEndpoints","fileResult","sum","t","allTasks","crypto","pool","WorkerPool","results","ft","i","result","fileName","analyzedFiles","a","b","ep","joinedOperations","routerName","routerPattern","node","nodeText","resolveEndpointPath","t1","endpoint","sectionTimings","parseEndpoint","sourceFile","nameOfUseApiHeader","discoverImportedName","SyntaxKind","targetNode","values","getValuesOfObjectLiteral","collapseObject","v","value","models","nameOfUseExposeApiModel","nameOfUseExposeNamedApiModels","firstChild","parseExposedModel","parseNamedExposedModels","model"],"mappings":"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"}
1
+ {"version":3,"file":"analyzerModule.cjs","sources":["../../../src/openapi/analyzerModule/analyzerModule.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { existsSync } from 'fs'\nimport * as path from 'path'\nimport { fileURLToPath } from 'url'\n\nfunction resolveWorkerUrl(): URL {\n\tconst candidates = ['./analyzerWorker.mjs', './analyzerWorker.test.mjs']\n\tfor (const candidate of candidates) {\n\t\tconst url = new URL(candidate, import.meta.url)\n\t\tif (existsSync(fileURLToPath(url))) {\n\t\t\treturn url\n\t\t}\n\t}\n\tthrow new Error(\n\t\t'analyzerWorker.mjs not found. Run yarn build, or run tests via yarn test (which compiles the worker first).',\n\t)\n}\nimport { SourceFile, SyntaxKind } from 'ts-morph'\nimport { Project } from 'ts-morph'\n\nimport { Logger } from '../../utils/logger'\nimport { discoverImportedName } from '../discoveryModule/discoverImports/discoverImports'\nimport {\n\tDiscoveredSourceFile,\n\tdiscoverRouterFiles,\n} from '../discoveryModule/discoverRouterFiles/discoverRouterFiles'\nimport { discoverRouters } from '../discoveryModule/discoverRouters/discoverRouters'\nimport { ApiDocsHeader, OpenApiManager } from '../manager/OpenApiManager'\nimport { EndpointData, ExposedModelData } from '../types'\nimport { getSourceFileTimestamp, MtimeCache, TimestampCache } from './getSourceFileTimestamp'\nimport { getValuesOfObjectLiteral, resolveEndpointPath } from './nodeParsers'\nimport { parseEndpoint, SectionTiming } from './parseEndpoint'\nimport { parseExposedModel, parseNamedExposedModels } from './parseExposedModels'\nimport { SourceFileCache } from './sourceFileCache'\nimport { WorkerPool, WorkerResult, WorkerTask } from './workerPool'\n\ntype Props = {\n\tlogLevel?: Parameters<(typeof Logger)['setLevel']>[0]\n\ttsconfigPath: string\n\tsourceFilePaths?: string[]\n\tsourceFileDiscovery?: boolean | FileDiscoveryConfig\n\tincremental?:\n\t\t| boolean\n\t\t| {\n\t\t\t\tcachePath: string\n\t\t }\n\tprofiling?: 'stats' | 'off' | 'debug'\n\tworkers?: boolean\n}\n\ntype FileDiscoveryConfig = {\n\trootPath: string\n}\n\ntype EndpointTiming = { method: string; path: string; timing: number; sectionTimings: SectionTiming[] }\n\n/**\n * Number of uncached files at or below which analysis runs inline on the (already-warm) main-thread\n * Project instead of fanning out to worker threads. Each worker pays a multi-second cold-start to\n * build its own Project, so parallelism only wins once there are several files to share that cost.\n */\nconst INLINE_ANALYSIS_FILE_THRESHOLD = 2\n\n/**\n * @param tsconfigPath Path to tsconfig file relative to project root\n * @param sourceFilePaths Array of router source files relative to project root\n */\nexport const prepareOpenApiSpec = async ({\n\tlogLevel,\n\ttsconfigPath,\n\tsourceFilePaths,\n\tsourceFileDiscovery,\n\tincremental,\n\tprofiling = 'stats',\n\tworkers = false,\n}: Props): Promise<void> => {\n\tconst openApiManager = OpenApiManager.getInstance()\n\n\tif (openApiManager.isReady()) {\n\t\treturn\n\t}\n\n\tif (logLevel) {\n\t\tLogger.setLevel(logLevel)\n\t}\n\n\tLogger.info('Preparing OpenAPI spec')\n\n\tconst project = new Project({\n\t\ttsConfigFilePath: path.resolve(tsconfigPath),\n\t\tskipFileDependencyResolution: true,\n\t})\n\n\tconst { explicitRouters, discoveredRouterFiles, allSourceFiles } = (() => {\n\t\tconst sourceFilesToAdd = sourceFilePaths ?? []\n\t\tconst resolvedSourceFilePaths = sourceFilesToAdd.map((filepath) => path.resolve(filepath))\n\t\tconst sourceFiles = resolvedSourceFilePaths.map((filePath) => project.getSourceFileOrThrow(filePath))\n\t\tconst explicitRouters = sourceFiles.flatMap((file) => ({\n\t\t\tfileName: file.getFilePath(),\n\t\t\tsourceFile: file,\n\t\t\trouters: discoverRouters(file),\n\t\t}))\n\n\t\tconst { discoveredRouterFiles, discoveredSourceFiles } = (() => {\n\t\t\tif (sourceFileDiscovery === false) {\n\t\t\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t\t\t}\n\n\t\t\tconst startTime = performance.now()\n\t\t\tconst files = discoverRouterFiles({\n\t\t\t\ttargetPath: typeof sourceFileDiscovery === 'object' ? sourceFileDiscovery.rootPath : '.',\n\t\t\t\tproject,\n\t\t\t})\n\t\t\tif (profiling !== 'off') {\n\t\t\t\tLogger.info(`File discovery took ${Math.round(performance.now() - startTime)}ms`)\n\t\t\t}\n\t\t\treturn files\n\t\t})()\n\n\t\tconst allSourceFiles = sourceFiles.reduce(\n\t\t\t(acc, current) =>\n\t\t\t\tacc.some((r) => r.getFilePath() === current.getFilePath()) ? acc : acc.concat(current),\n\t\t\tdiscoveredSourceFiles,\n\t\t)\n\n\t\treturn { explicitRouters, discoveredRouterFiles, allSourceFiles }\n\t})()\n\n\tconst filesToAnalyze = explicitRouters.reduce(\n\t\t(acc, current) => (acc.some((r) => r.fileName === current.fileName) ? acc : acc.concat(current)),\n\t\tdiscoveredRouterFiles,\n\t)\n\n\tconst apiHeaders = allSourceFiles\n\t\t.flatMap((file) => analyzeSourceFileApiHeader(file))\n\t\t.filter((headers) => !!headers)\n\tif (apiHeaders.length > 0 && apiHeaders[0]) {\n\t\topenApiManager.setHeader(apiHeaders[0])\n\t}\n\n\tconst exposedModels = allSourceFiles.flatMap((file) => analyzeSourceFileExposedModels(file))\n\n\topenApiManager.setExposedModels(exposedModels)\n\n\tconst cachePath = (() => {\n\t\tif (typeof incremental === 'object' && incremental.cachePath) {\n\t\t\treturn incremental.cachePath\n\t\t}\n\t\treturn path.resolve(process.cwd(), 'node_modules', '.cache', 'moonflower')\n\t})()\n\tconst endpoints = await analyzeMultipleSourceFiles(filesToAnalyze, {\n\t\tincremental: incremental !== false,\n\t\tcachePath,\n\t\ttimestampCache: {},\n\t\tprofiling,\n\t\ttsconfigPath: path.resolve(tsconfigPath),\n\t\tworkers,\n\t})\n\n\topenApiManager.setStats({\n\t\tdiscoveredRouterFiles: discoveredRouterFiles.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t\texplicitRouterFiles: explicitRouters.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t})\n\n\topenApiManager.setEndpoints(endpoints)\n\topenApiManager.markAsReady()\n}\n\nexport const analyzeMultipleSourceFiles = async (\n\tfiles: DiscoveredSourceFile[],\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t\ttsconfigPath: string\n\t\tworkers?: boolean\n\t},\n\tfilterEndpointPaths?: string[],\n): Promise<EndpointData[]> => {\n\tconst profiling = config.profiling ?? 'stats'\n\tconst startTime = performance.now()\n\n\t// Separate cached files from those needing analysis\n\ttype CachedFile = { endpoints: EndpointData[]; fileName: string; timing: 0; endpointTimings: [] }\n\ttype UncachedFile = { file: DiscoveredSourceFile; timestamp: number }\n\n\tconst cached: CachedFile[] = []\n\tconst uncached: UncachedFile[] = []\n\n\tconst freshnessCheckStart = performance.now()\n\tconst mtimeCache: MtimeCache = new Map()\n\tfor (const file of files) {\n\t\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache, mtimeCache)\n\t\tconst hit = config.incremental\n\t\t\t? SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\t\t\t: null\n\t\tif (hit) {\n\t\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\t\tcached.push({ endpoints: hit.endpoints, fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t\t} else {\n\t\t\tuncached.push({ file, timestamp })\n\t\t}\n\t}\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Cache freshness check took ${Math.round(performance.now() - freshnessCheckStart)}ms`)\n\t}\n\n\tif (uncached.length === 0) {\n\t\tif (profiling !== 'off') {\n\t\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t\t}\n\t\treturn cached.flatMap((f) => f.endpoints)\n\t}\n\n\ttype FileResult = {\n\t\tendpoints: EndpointData[]\n\t\tfileName: string\n\t\ttiming: number\n\t\tendpointTimings: EndpointTiming[]\n\t}\n\n\tconst byFile = new Map<string, FileResult>()\n\tfor (const { file } of uncached) {\n\t\tbyFile.set(file.fileName, { endpoints: [], fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t}\n\n\tconst useWorkers = config.workers !== false\n\tif (!useWorkers || uncached.length <= INLINE_ANALYSIS_FILE_THRESHOLD) {\n\t\tfor (const { file } of uncached) {\n\t\t\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\t\t\tconst fileResult = byFile.get(file.fileName)!\n\t\t\tfileResult.endpoints = endpoints\n\t\t\tfileResult.endpointTimings = endpointTimings\n\t\t\tfileResult.timing = endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t} else {\n\t\ttype FileTask = { task: WorkerTask; fileName: string }\n\t\tconst allTasks: FileTask[] = uncached.map(({ file }) => ({\n\t\t\tfileName: file.fileName,\n\t\t\ttask: {\n\t\t\t\ttaskId: crypto.randomUUID(),\n\t\t\t\ttsconfigPath: config.tsconfigPath,\n\t\t\t\tsourceFilePath: file.sourceFile.getFilePath(),\n\t\t\t\trouterNames: file.routers.named,\n\t\t\t\tfilterEndpointPaths,\n\t\t\t},\n\t\t}))\n\n\t\tconst pool = new WorkerPool(resolveWorkerUrl(), allTasks.length)\n\t\tlet results: WorkerResult[]\n\t\ttry {\n\t\t\tresults = await pool.runAll(allTasks.map((ft) => ft.task))\n\t\t} finally {\n\t\t\tpool.terminate()\n\t\t}\n\n\t\t// Each result maps 1:1 to a file task.\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst result = results[i]\n\t\t\tconst fileName = allTasks[i].fileName\n\t\t\tconst fileResult = byFile.get(fileName)!\n\n\t\t\tif ('error' in result) {\n\t\t\t\tLogger.error(`[${fileName}] Worker error: ${result.error}`)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfileResult.endpoints = result.endpoints\n\t\t\tfileResult.endpointTimings = result.endpointTimings\n\t\t\tfileResult.timing = result.endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t}\n\n\t// Write cache for each uncached file\n\tfor (const { file, timestamp } of uncached) {\n\t\tconst fileResult = byFile.get(file.fileName)!\n\t\tif (fileResult.endpoints.length > 0) {\n\t\t\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, fileResult.endpoints)\n\t\t}\n\t}\n\n\tconst analyzedFiles = [...cached, ...Array.from(byFile.values())]\n\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t}\n\n\tif (profiling === 'stats') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.filter((t) => t.timeTaken > 500)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t})\n\t} else if (profiling === 'debug') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing, endpointTimings: f.endpointTimings }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t\tt.endpointTimings\n\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t.forEach((ep) => {\n\t\t\t\t\t\tLogger.info(` - ${ep.method} ${ep.path} (${Math.round(ep.timing)}ms)`)\n\t\t\t\t\t\tep.sectionTimings\n\t\t\t\t\t\t\t.filter((s) => s.timing >= 1)\n\t\t\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t\t\t.forEach((s) => {\n\t\t\t\t\t\t\t\tLogger.info(` - ${s.section}: ${Math.round(s.timing)}ms`)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t})\n\t}\n\n\treturn analyzedFiles.flatMap((f) => f.endpoints)\n}\n\nexport const analyzeSourceFileWithCache = (\n\tfile: DiscoveredSourceFile,\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t},\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; timing: number; endpointTimings: EndpointTiming[] } => {\n\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache)\n\tconst cachedResults = SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\n\tif (cachedResults) {\n\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\treturn { endpoints: cachedResults.endpoints, timing: 0, endpointTimings: [] }\n\t}\n\tLogger.debug(`[${file.fileName}] Analyzing...`)\n\n\tconst t1 = performance.now()\n\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\tconst t2 = performance.now()\n\tLogger.debug(`[${file.fileName}] Analyzed in ${t2 - t1}ms`)\n\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, endpoints)\n\treturn { endpoints, timing: t2 - t1, endpointTimings }\n}\n\nexport const analyzeSourceFileEndpoints = (\n\tfile: DiscoveredSourceFile,\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; endpointTimings: EndpointTiming[] } => {\n\tconst endpoints: EndpointData[] = []\n\tconst endpointTimings: EndpointTiming[] = []\n\tconst operations = ['get', 'post', 'put', 'delete', 'del', 'patch']\n\tconst joinedOperations = operations.join('|')\n\n\tfile.routers.named.forEach((routerName) => {\n\t\tconst routerPattern = new RegExp(`${routerName}\\\\.(?:${joinedOperations})`)\n\t\tfile.sourceFile.forEachChild((node) => {\n\t\t\tconst nodeText = node.getText()\n\n\t\t\tif (routerPattern.test(nodeText)) {\n\t\t\t\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\t\t\t\tif (filterEndpointPaths && !filterEndpointPaths.some((path) => endpointPath.includes(path))) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst t1 = performance.now()\n\t\t\t\tconst { endpoint, sectionTimings } = parseEndpoint(node, file.fileName)\n\t\t\t\tendpointTimings.push({\n\t\t\t\t\tmethod: endpoint.method,\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\ttiming: performance.now() - t1,\n\t\t\t\t\tsectionTimings,\n\t\t\t\t})\n\t\t\t\tendpoints.push(endpoint)\n\t\t\t}\n\t\t})\n\t})\n\n\treturn { endpoints, endpointTimings }\n}\n\nexport const analyzeSourceFileApiHeader = (sourceFile: SourceFile): ApiDocsHeader | null => {\n\tconst nameOfUseApiHeader = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useApiHeader',\n\t})\n\n\tif (!nameOfUseApiHeader) {\n\t\treturn null\n\t}\n\n\tconst node = sourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.find((node) => nameOfUseApiHeader && node.getText().startsWith(nameOfUseApiHeader))\n\n\tif (!node) {\n\t\treturn null\n\t}\n\n\tconst targetNode = node.getFirstDescendantByKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\tconst values = getValuesOfObjectLiteral(targetNode)\n\n\tconst collapseObject = (v: string | string[] | typeof values): any => {\n\t\tif (typeof v === 'string') {\n\t\t\treturn v\n\t\t}\n\t\tif (Array.isArray(v) && v.every((value) => typeof value === 'string')) {\n\t\t\treturn v\n\t\t}\n\n\t\treturn v.reduce((acc, current) => {\n\t\t\tif (typeof current === 'string') {\n\t\t\t\treturn acc\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[current.identifier]: collapseObject(current.value as string[]),\n\t\t\t}\n\t\t}, {})\n\t}\n\treturn collapseObject(values)\n}\n\nexport const analyzeSourceFileExposedModels = (sourceFile: SourceFile): ExposedModelData[] => {\n\tconst models: ExposedModelData[] = []\n\n\tconst nameOfUseExposeApiModel = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeApiModel',\n\t})\n\n\tconst nameOfUseExposeNamedApiModels = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeNamedApiModels',\n\t})\n\n\tsourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.map((node) => {\n\t\t\tif (nameOfUseExposeApiModel && node.getText().startsWith(nameOfUseExposeApiModel)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tmodels.push(parseExposedModel(firstChild))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (nameOfUseExposeNamedApiModels && node.getText().startsWith(nameOfUseExposeNamedApiModels)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst parsedModels = parseNamedExposedModels(firstChild)\n\t\t\t\tparsedModels.forEach((model) => models.push(model))\n\t\t\t}\n\t\t})\n\treturn models\n}\n"],"names":["resolveWorkerUrl","candidates","candidate","url","_documentCurrentScript","existsSync","fileURLToPath","INLINE_ANALYSIS_FILE_THRESHOLD","prepareOpenApiSpec","logLevel","tsconfigPath","sourceFilePaths","sourceFileDiscovery","incremental","profiling","workers","openApiManager","OpenApiManager","Logger","project","Project","path","explicitRouters","discoveredRouterFiles","allSourceFiles","sourceFiles","filepath","filePath","file","discoverRouters","discoveredSourceFiles","startTime","files","discoverRouterFiles","acc","current","r","filesToAnalyze","apiHeaders","analyzeSourceFileApiHeader","headers","exposedModels","analyzeSourceFileExposedModels","cachePath","endpoints","analyzeMultipleSourceFiles","e","config","filterEndpointPaths","cached","uncached","freshnessCheckStart","mtimeCache","timestamp","getSourceFileTimestamp","hit","SourceFileCache","f","byFile","endpointTimings","analyzeSourceFileEndpoints","fileResult","sum","t","allTasks","crypto","pool","WorkerPool","results","ft","i","result","fileName","analyzedFiles","a","b","ep","joinedOperations","routerName","routerPattern","node","nodeText","resolveEndpointPath","t1","endpoint","sectionTimings","parseEndpoint","sourceFile","nameOfUseApiHeader","discoverImportedName","SyntaxKind","targetNode","values","getValuesOfObjectLiteral","collapseObject","v","value","models","nameOfUseExposeApiModel","nameOfUseExposeNamedApiModels","firstChild","parseExposedModel","parseNamedExposedModels","model"],"mappings":"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"}
@@ -38,27 +38,27 @@ const Y = 2, fe = async ({
38
38
  if (r.isReady())
39
39
  return;
40
40
  l && F.setLevel(l), F.info("Preparing OpenAPI spec");
41
- const h = new j({
41
+ const u = new j({
42
42
  tsConfigFilePath: M.resolve(n),
43
43
  skipFileDependencyResolution: !0
44
44
  }), { explicitRouters: g, discoveredRouterFiles: x, allSourceFiles: T } = (() => {
45
- const p = (d ?? []).map((u) => M.resolve(u)).map((u) => h.getSourceFileOrThrow(u)), P = p.flatMap((u) => ({
46
- fileName: u.getFilePath(),
47
- sourceFile: u,
48
- routers: W(u)
49
- })), { discoveredRouterFiles: C, discoveredSourceFiles: S } = (() => {
45
+ const p = (d ?? []).map((h) => M.resolve(h)).map((h) => u.getSourceFileOrThrow(h)), P = p.flatMap((h) => ({
46
+ fileName: h.getFilePath(),
47
+ sourceFile: h,
48
+ routers: W(h)
49
+ })), { discoveredRouterFiles: S, discoveredSourceFiles: A } = (() => {
50
50
  if (m === !1)
51
51
  return { discoveredRouterFiles: [], discoveredSourceFiles: [] };
52
- const u = performance.now(), k = z({
52
+ const h = performance.now(), k = z({
53
53
  targetPath: typeof m == "object" ? m.rootPath : ".",
54
- tsConfigPath: n
54
+ project: u
55
55
  });
56
- return f !== "off" && F.info(`File discovery took ${Math.round(performance.now() - u)}ms`), k;
57
- })(), A = p.reduce(
58
- (u, k) => u.some(($) => $.getFilePath() === k.getFilePath()) ? u : u.concat(k),
59
- S
56
+ return f !== "off" && F.info(`File discovery took ${Math.round(performance.now() - h)}ms`), k;
57
+ })(), C = p.reduce(
58
+ (h, k) => h.some(($) => $.getFilePath() === k.getFilePath()) ? h : h.concat(k),
59
+ A
60
60
  );
61
- return { explicitRouters: P, discoveredRouterFiles: C, allSourceFiles: A };
61
+ return { explicitRouters: P, discoveredRouterFiles: S, allSourceFiles: C };
62
62
  })(), e = g.reduce(
63
63
  (i, N) => i.some((p) => p.fileName === N.fileName) ? i : i.concat(N),
64
64
  x
@@ -91,9 +91,9 @@ const Y = 2, fe = async ({
91
91
  }))
92
92
  }), r.setEndpoints(y), r.markAsReady();
93
93
  }, q = async (l, n, d) => {
94
- const m = n.profiling ?? "stats", c = performance.now(), f = [], t = [], r = performance.now(), h = /* @__PURE__ */ new Map();
94
+ const m = n.profiling ?? "stats", c = performance.now(), f = [], t = [], r = performance.now(), u = /* @__PURE__ */ new Map();
95
95
  for (const e of l) {
96
- const o = b(e.sourceFile, n.timestampCache, h), s = n.incremental ? w.getCachedResults(e.sourceFile, o, n.cachePath) : null;
96
+ const o = b(e.sourceFile, n.timestampCache, u), s = n.incremental ? w.getCachedResults(e.sourceFile, o, n.cachePath) : null;
97
97
  s ? (F.debug(`[${e.fileName}] Found cached results`), f.push({ endpoints: s.endpoints, fileName: e.fileName, timing: 0, endpointTimings: [] })) : t.push({ file: e, timestamp: o });
98
98
  }
99
99
  if (m !== "off" && F.info(`Cache freshness check took ${Math.round(performance.now() - r)}ms`), t.length === 0)
@@ -150,11 +150,11 @@ const Y = 2, fe = async ({
150
150
  const d = [], m = [], f = ["get", "post", "put", "delete", "del", "patch"].join("|");
151
151
  return l.routers.named.forEach((t) => {
152
152
  const r = new RegExp(`${t}\\.(?:${f})`);
153
- l.sourceFile.forEachChild((h) => {
154
- const g = h.getText();
153
+ l.sourceFile.forEachChild((u) => {
154
+ const g = u.getText();
155
155
  if (r.test(g)) {
156
- H(h);
157
- const x = performance.now(), { endpoint: T, sectionTimings: e } = K(h, l.fileName);
156
+ H(u);
157
+ const x = performance.now(), { endpoint: T, sectionTimings: e } = K(u, l.fileName);
158
158
  m.push({
159
159
  method: T.method,
160
160
  path: T.path,
@@ -174,9 +174,9 @@ const Y = 2, fe = async ({
174
174
  const d = l.forEachChildAsArray().filter((t) => t.isKind(E.ExpressionStatement)).find((t) => n && t.getText().startsWith(n));
175
175
  if (!d)
176
176
  return null;
177
- const m = d.getFirstDescendantByKindOrThrow(E.ObjectLiteralExpression), c = I(m), f = (t) => typeof t == "string" || Array.isArray(t) && t.every((r) => typeof r == "string") ? t : t.reduce((r, h) => typeof h == "string" ? r : {
177
+ const m = d.getFirstDescendantByKindOrThrow(E.ObjectLiteralExpression), c = I(m), f = (t) => typeof t == "string" || Array.isArray(t) && t.every((r) => typeof r == "string") ? t : t.reduce((r, u) => typeof u == "string" ? r : {
178
178
  ...r,
179
- [h.identifier]: f(h.value)
179
+ [u.identifier]: f(u.value)
180
180
  }, {});
181
181
  return f(c);
182
182
  }, Q = (l) => {
@@ -1 +1 @@
1
- {"version":3,"file":"analyzerModule.mjs","sources":["../../../src/openapi/analyzerModule/analyzerModule.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { existsSync } from 'fs'\nimport * as path from 'path'\nimport { fileURLToPath } from 'url'\n\nfunction resolveWorkerUrl(): URL {\n\tconst candidates = ['./analyzerWorker.mjs', './analyzerWorker.test.mjs']\n\tfor (const candidate of candidates) {\n\t\tconst url = new URL(candidate, import.meta.url)\n\t\tif (existsSync(fileURLToPath(url))) {\n\t\t\treturn url\n\t\t}\n\t}\n\tthrow new Error(\n\t\t'analyzerWorker.mjs not found. Run yarn build, or run tests via yarn test (which compiles the worker first).',\n\t)\n}\nimport { SourceFile, SyntaxKind } from 'ts-morph'\nimport { Project } from 'ts-morph'\n\nimport { Logger } from '../../utils/logger'\nimport { discoverImportedName } from '../discoveryModule/discoverImports/discoverImports'\nimport {\n\tDiscoveredSourceFile,\n\tdiscoverRouterFiles,\n} from '../discoveryModule/discoverRouterFiles/discoverRouterFiles'\nimport { discoverRouters } from '../discoveryModule/discoverRouters/discoverRouters'\nimport { ApiDocsHeader, OpenApiManager } from '../manager/OpenApiManager'\nimport { EndpointData, ExposedModelData } from '../types'\nimport { getSourceFileTimestamp, MtimeCache, TimestampCache } from './getSourceFileTimestamp'\nimport { getValuesOfObjectLiteral, resolveEndpointPath } from './nodeParsers'\nimport { parseEndpoint, SectionTiming } from './parseEndpoint'\nimport { parseExposedModel, parseNamedExposedModels } from './parseExposedModels'\nimport { SourceFileCache } from './sourceFileCache'\nimport { WorkerPool, WorkerResult, WorkerTask } from './workerPool'\n\ntype Props = {\n\tlogLevel?: Parameters<(typeof Logger)['setLevel']>[0]\n\ttsconfigPath: string\n\tsourceFilePaths?: string[]\n\tsourceFileDiscovery?: boolean | FileDiscoveryConfig\n\tincremental?:\n\t\t| boolean\n\t\t| {\n\t\t\t\tcachePath: string\n\t\t }\n\tprofiling?: 'stats' | 'off' | 'debug'\n\tworkers?: boolean\n}\n\ntype FileDiscoveryConfig = {\n\trootPath: string\n}\n\ntype EndpointTiming = { method: string; path: string; timing: number; sectionTimings: SectionTiming[] }\n\n/**\n * Number of uncached files at or below which analysis runs inline on the (already-warm) main-thread\n * Project instead of fanning out to worker threads. Each worker pays a multi-second cold-start to\n * build its own Project, so parallelism only wins once there are several files to share that cost.\n */\nconst INLINE_ANALYSIS_FILE_THRESHOLD = 2\n\n/**\n * @param tsconfigPath Path to tsconfig file relative to project root\n * @param sourceFilePaths Array of router source files relative to project root\n */\nexport const prepareOpenApiSpec = async ({\n\tlogLevel,\n\ttsconfigPath,\n\tsourceFilePaths,\n\tsourceFileDiscovery,\n\tincremental,\n\tprofiling = 'stats',\n\tworkers = false,\n}: Props): Promise<void> => {\n\tconst openApiManager = OpenApiManager.getInstance()\n\n\tif (openApiManager.isReady()) {\n\t\treturn\n\t}\n\n\tif (logLevel) {\n\t\tLogger.setLevel(logLevel)\n\t}\n\n\tLogger.info('Preparing OpenAPI spec')\n\n\tconst project = new Project({\n\t\ttsConfigFilePath: path.resolve(tsconfigPath),\n\t\tskipFileDependencyResolution: true,\n\t})\n\n\tconst { explicitRouters, discoveredRouterFiles, allSourceFiles } = (() => {\n\t\tconst sourceFilesToAdd = sourceFilePaths ?? []\n\t\tconst resolvedSourceFilePaths = sourceFilesToAdd.map((filepath) => path.resolve(filepath))\n\t\tconst sourceFiles = resolvedSourceFilePaths.map((filePath) => project.getSourceFileOrThrow(filePath))\n\t\tconst explicitRouters = sourceFiles.flatMap((file) => ({\n\t\t\tfileName: file.getFilePath(),\n\t\t\tsourceFile: file,\n\t\t\trouters: discoverRouters(file),\n\t\t}))\n\n\t\tconst { discoveredRouterFiles, discoveredSourceFiles } = (() => {\n\t\t\tif (sourceFileDiscovery === false) {\n\t\t\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t\t\t}\n\n\t\t\tconst startTime = performance.now()\n\t\t\tconst files = discoverRouterFiles({\n\t\t\t\ttargetPath: typeof sourceFileDiscovery === 'object' ? sourceFileDiscovery.rootPath : '.',\n\t\t\t\ttsConfigPath: tsconfigPath,\n\t\t\t})\n\t\t\tif (profiling !== 'off') {\n\t\t\t\tLogger.info(`File discovery took ${Math.round(performance.now() - startTime)}ms`)\n\t\t\t}\n\t\t\treturn files\n\t\t})()\n\n\t\tconst allSourceFiles = sourceFiles.reduce(\n\t\t\t(acc, current) =>\n\t\t\t\tacc.some((r) => r.getFilePath() === current.getFilePath()) ? acc : acc.concat(current),\n\t\t\tdiscoveredSourceFiles,\n\t\t)\n\n\t\treturn { explicitRouters, discoveredRouterFiles, allSourceFiles }\n\t})()\n\n\tconst filesToAnalyze = explicitRouters.reduce(\n\t\t(acc, current) => (acc.some((r) => r.fileName === current.fileName) ? acc : acc.concat(current)),\n\t\tdiscoveredRouterFiles,\n\t)\n\n\tconst apiHeaders = allSourceFiles\n\t\t.flatMap((file) => analyzeSourceFileApiHeader(file))\n\t\t.filter((headers) => !!headers)\n\tif (apiHeaders.length > 0 && apiHeaders[0]) {\n\t\topenApiManager.setHeader(apiHeaders[0])\n\t}\n\n\tconst exposedModels = allSourceFiles.flatMap((file) => analyzeSourceFileExposedModels(file))\n\n\topenApiManager.setExposedModels(exposedModels)\n\n\tconst cachePath = (() => {\n\t\tif (typeof incremental === 'object' && incremental.cachePath) {\n\t\t\treturn incremental.cachePath\n\t\t}\n\t\treturn path.resolve(process.cwd(), 'node_modules', '.cache', 'moonflower')\n\t})()\n\tconst endpoints = await analyzeMultipleSourceFiles(filesToAnalyze, {\n\t\tincremental: incremental !== false,\n\t\tcachePath,\n\t\ttimestampCache: {},\n\t\tprofiling,\n\t\ttsconfigPath: path.resolve(tsconfigPath),\n\t\tworkers,\n\t})\n\n\topenApiManager.setStats({\n\t\tdiscoveredRouterFiles: discoveredRouterFiles.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t\texplicitRouterFiles: explicitRouters.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t})\n\n\topenApiManager.setEndpoints(endpoints)\n\topenApiManager.markAsReady()\n}\n\nexport const analyzeMultipleSourceFiles = async (\n\tfiles: DiscoveredSourceFile[],\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t\ttsconfigPath: string\n\t\tworkers?: boolean\n\t},\n\tfilterEndpointPaths?: string[],\n): Promise<EndpointData[]> => {\n\tconst profiling = config.profiling ?? 'stats'\n\tconst startTime = performance.now()\n\n\t// Separate cached files from those needing analysis\n\ttype CachedFile = { endpoints: EndpointData[]; fileName: string; timing: 0; endpointTimings: [] }\n\ttype UncachedFile = { file: DiscoveredSourceFile; timestamp: number }\n\n\tconst cached: CachedFile[] = []\n\tconst uncached: UncachedFile[] = []\n\n\tconst freshnessCheckStart = performance.now()\n\tconst mtimeCache: MtimeCache = new Map()\n\tfor (const file of files) {\n\t\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache, mtimeCache)\n\t\tconst hit = config.incremental\n\t\t\t? SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\t\t\t: null\n\t\tif (hit) {\n\t\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\t\tcached.push({ endpoints: hit.endpoints, fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t\t} else {\n\t\t\tuncached.push({ file, timestamp })\n\t\t}\n\t}\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Cache freshness check took ${Math.round(performance.now() - freshnessCheckStart)}ms`)\n\t}\n\n\tif (uncached.length === 0) {\n\t\tif (profiling !== 'off') {\n\t\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t\t}\n\t\treturn cached.flatMap((f) => f.endpoints)\n\t}\n\n\ttype FileResult = {\n\t\tendpoints: EndpointData[]\n\t\tfileName: string\n\t\ttiming: number\n\t\tendpointTimings: EndpointTiming[]\n\t}\n\n\tconst byFile = new Map<string, FileResult>()\n\tfor (const { file } of uncached) {\n\t\tbyFile.set(file.fileName, { endpoints: [], fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t}\n\n\tconst useWorkers = config.workers !== false\n\tif (!useWorkers || uncached.length <= INLINE_ANALYSIS_FILE_THRESHOLD) {\n\t\tfor (const { file } of uncached) {\n\t\t\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\t\t\tconst fileResult = byFile.get(file.fileName)!\n\t\t\tfileResult.endpoints = endpoints\n\t\t\tfileResult.endpointTimings = endpointTimings\n\t\t\tfileResult.timing = endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t} else {\n\t\ttype FileTask = { task: WorkerTask; fileName: string }\n\t\tconst allTasks: FileTask[] = uncached.map(({ file }) => ({\n\t\t\tfileName: file.fileName,\n\t\t\ttask: {\n\t\t\t\ttaskId: crypto.randomUUID(),\n\t\t\t\ttsconfigPath: config.tsconfigPath,\n\t\t\t\tsourceFilePath: file.sourceFile.getFilePath(),\n\t\t\t\trouterNames: file.routers.named,\n\t\t\t\tfilterEndpointPaths,\n\t\t\t},\n\t\t}))\n\n\t\tconst pool = new WorkerPool(resolveWorkerUrl(), allTasks.length)\n\t\tlet results: WorkerResult[]\n\t\ttry {\n\t\t\tresults = await pool.runAll(allTasks.map((ft) => ft.task))\n\t\t} finally {\n\t\t\tpool.terminate()\n\t\t}\n\n\t\t// Each result maps 1:1 to a file task.\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst result = results[i]\n\t\t\tconst fileName = allTasks[i].fileName\n\t\t\tconst fileResult = byFile.get(fileName)!\n\n\t\t\tif ('error' in result) {\n\t\t\t\tLogger.error(`[${fileName}] Worker error: ${result.error}`)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfileResult.endpoints = result.endpoints\n\t\t\tfileResult.endpointTimings = result.endpointTimings\n\t\t\tfileResult.timing = result.endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t}\n\n\t// Write cache for each uncached file\n\tfor (const { file, timestamp } of uncached) {\n\t\tconst fileResult = byFile.get(file.fileName)!\n\t\tif (fileResult.endpoints.length > 0) {\n\t\t\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, fileResult.endpoints)\n\t\t}\n\t}\n\n\tconst analyzedFiles = [...cached, ...Array.from(byFile.values())]\n\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t}\n\n\tif (profiling === 'stats') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.filter((t) => t.timeTaken > 500)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t})\n\t} else if (profiling === 'debug') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing, endpointTimings: f.endpointTimings }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t\tt.endpointTimings\n\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t.forEach((ep) => {\n\t\t\t\t\t\tLogger.info(` - ${ep.method} ${ep.path} (${Math.round(ep.timing)}ms)`)\n\t\t\t\t\t\tep.sectionTimings\n\t\t\t\t\t\t\t.filter((s) => s.timing >= 1)\n\t\t\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t\t\t.forEach((s) => {\n\t\t\t\t\t\t\t\tLogger.info(` - ${s.section}: ${Math.round(s.timing)}ms`)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t})\n\t}\n\n\treturn analyzedFiles.flatMap((f) => f.endpoints)\n}\n\nexport const analyzeSourceFileWithCache = (\n\tfile: DiscoveredSourceFile,\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t},\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; timing: number; endpointTimings: EndpointTiming[] } => {\n\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache)\n\tconst cachedResults = SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\n\tif (cachedResults) {\n\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\treturn { endpoints: cachedResults.endpoints, timing: 0, endpointTimings: [] }\n\t}\n\tLogger.debug(`[${file.fileName}] Analyzing...`)\n\n\tconst t1 = performance.now()\n\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\tconst t2 = performance.now()\n\tLogger.debug(`[${file.fileName}] Analyzed in ${t2 - t1}ms`)\n\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, endpoints)\n\treturn { endpoints, timing: t2 - t1, endpointTimings }\n}\n\nexport const analyzeSourceFileEndpoints = (\n\tfile: DiscoveredSourceFile,\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; endpointTimings: EndpointTiming[] } => {\n\tconst endpoints: EndpointData[] = []\n\tconst endpointTimings: EndpointTiming[] = []\n\tconst operations = ['get', 'post', 'put', 'delete', 'del', 'patch']\n\tconst joinedOperations = operations.join('|')\n\n\tfile.routers.named.forEach((routerName) => {\n\t\tconst routerPattern = new RegExp(`${routerName}\\\\.(?:${joinedOperations})`)\n\t\tfile.sourceFile.forEachChild((node) => {\n\t\t\tconst nodeText = node.getText()\n\n\t\t\tif (routerPattern.test(nodeText)) {\n\t\t\t\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\t\t\t\tif (filterEndpointPaths && !filterEndpointPaths.some((path) => endpointPath.includes(path))) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst t1 = performance.now()\n\t\t\t\tconst { endpoint, sectionTimings } = parseEndpoint(node, file.fileName)\n\t\t\t\tendpointTimings.push({\n\t\t\t\t\tmethod: endpoint.method,\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\ttiming: performance.now() - t1,\n\t\t\t\t\tsectionTimings,\n\t\t\t\t})\n\t\t\t\tendpoints.push(endpoint)\n\t\t\t}\n\t\t})\n\t})\n\n\treturn { endpoints, endpointTimings }\n}\n\nexport const analyzeSourceFileApiHeader = (sourceFile: SourceFile): ApiDocsHeader | null => {\n\tconst nameOfUseApiHeader = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useApiHeader',\n\t})\n\n\tif (!nameOfUseApiHeader) {\n\t\treturn null\n\t}\n\n\tconst node = sourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.find((node) => nameOfUseApiHeader && node.getText().startsWith(nameOfUseApiHeader))\n\n\tif (!node) {\n\t\treturn null\n\t}\n\n\tconst targetNode = node.getFirstDescendantByKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\tconst values = getValuesOfObjectLiteral(targetNode)\n\n\tconst collapseObject = (v: string | string[] | typeof values): any => {\n\t\tif (typeof v === 'string') {\n\t\t\treturn v\n\t\t}\n\t\tif (Array.isArray(v) && v.every((value) => typeof value === 'string')) {\n\t\t\treturn v\n\t\t}\n\n\t\treturn v.reduce((acc, current) => {\n\t\t\tif (typeof current === 'string') {\n\t\t\t\treturn acc\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[current.identifier]: collapseObject(current.value as string[]),\n\t\t\t}\n\t\t}, {})\n\t}\n\treturn collapseObject(values)\n}\n\nexport const analyzeSourceFileExposedModels = (sourceFile: SourceFile): ExposedModelData[] => {\n\tconst models: ExposedModelData[] = []\n\n\tconst nameOfUseExposeApiModel = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeApiModel',\n\t})\n\n\tconst nameOfUseExposeNamedApiModels = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeNamedApiModels',\n\t})\n\n\tsourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.map((node) => {\n\t\t\tif (nameOfUseExposeApiModel && node.getText().startsWith(nameOfUseExposeApiModel)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tmodels.push(parseExposedModel(firstChild))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (nameOfUseExposeNamedApiModels && node.getText().startsWith(nameOfUseExposeNamedApiModels)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst parsedModels = parseNamedExposedModels(firstChild)\n\t\t\t\tparsedModels.forEach((model) => models.push(model))\n\t\t\t}\n\t\t})\n\treturn models\n}\n"],"names":["resolveWorkerUrl","candidates","candidate","url","existsSync","fileURLToPath","INLINE_ANALYSIS_FILE_THRESHOLD","prepareOpenApiSpec","logLevel","tsconfigPath","sourceFilePaths","sourceFileDiscovery","incremental","profiling","workers","openApiManager","OpenApiManager","Logger","project","Project","path","explicitRouters","discoveredRouterFiles","allSourceFiles","sourceFiles","filepath","filePath","file","discoverRouters","discoveredSourceFiles","startTime","files","discoverRouterFiles","acc","current","r","filesToAnalyze","apiHeaders","analyzeSourceFileApiHeader","headers","exposedModels","analyzeSourceFileExposedModels","cachePath","endpoints","analyzeMultipleSourceFiles","e","config","filterEndpointPaths","cached","uncached","freshnessCheckStart","mtimeCache","timestamp","getSourceFileTimestamp","hit","SourceFileCache","f","byFile","endpointTimings","analyzeSourceFileEndpoints","fileResult","sum","t","allTasks","crypto","pool","WorkerPool","results","ft","i","result","fileName","analyzedFiles","a","b","ep","joinedOperations","routerName","routerPattern","node","nodeText","resolveEndpointPath","t1","endpoint","sectionTimings","parseEndpoint","sourceFile","nameOfUseApiHeader","discoverImportedName","SyntaxKind","targetNode","values","getValuesOfObjectLiteral","collapseObject","v","value","models","nameOfUseExposeApiModel","nameOfUseExposeNamedApiModels","firstChild","parseExposedModel","parseNamedExposedModels","model"],"mappings":"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"}
1
+ {"version":3,"file":"analyzerModule.mjs","sources":["../../../src/openapi/analyzerModule/analyzerModule.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { existsSync } from 'fs'\nimport * as path from 'path'\nimport { fileURLToPath } from 'url'\n\nfunction resolveWorkerUrl(): URL {\n\tconst candidates = ['./analyzerWorker.mjs', './analyzerWorker.test.mjs']\n\tfor (const candidate of candidates) {\n\t\tconst url = new URL(candidate, import.meta.url)\n\t\tif (existsSync(fileURLToPath(url))) {\n\t\t\treturn url\n\t\t}\n\t}\n\tthrow new Error(\n\t\t'analyzerWorker.mjs not found. Run yarn build, or run tests via yarn test (which compiles the worker first).',\n\t)\n}\nimport { SourceFile, SyntaxKind } from 'ts-morph'\nimport { Project } from 'ts-morph'\n\nimport { Logger } from '../../utils/logger'\nimport { discoverImportedName } from '../discoveryModule/discoverImports/discoverImports'\nimport {\n\tDiscoveredSourceFile,\n\tdiscoverRouterFiles,\n} from '../discoveryModule/discoverRouterFiles/discoverRouterFiles'\nimport { discoverRouters } from '../discoveryModule/discoverRouters/discoverRouters'\nimport { ApiDocsHeader, OpenApiManager } from '../manager/OpenApiManager'\nimport { EndpointData, ExposedModelData } from '../types'\nimport { getSourceFileTimestamp, MtimeCache, TimestampCache } from './getSourceFileTimestamp'\nimport { getValuesOfObjectLiteral, resolveEndpointPath } from './nodeParsers'\nimport { parseEndpoint, SectionTiming } from './parseEndpoint'\nimport { parseExposedModel, parseNamedExposedModels } from './parseExposedModels'\nimport { SourceFileCache } from './sourceFileCache'\nimport { WorkerPool, WorkerResult, WorkerTask } from './workerPool'\n\ntype Props = {\n\tlogLevel?: Parameters<(typeof Logger)['setLevel']>[0]\n\ttsconfigPath: string\n\tsourceFilePaths?: string[]\n\tsourceFileDiscovery?: boolean | FileDiscoveryConfig\n\tincremental?:\n\t\t| boolean\n\t\t| {\n\t\t\t\tcachePath: string\n\t\t }\n\tprofiling?: 'stats' | 'off' | 'debug'\n\tworkers?: boolean\n}\n\ntype FileDiscoveryConfig = {\n\trootPath: string\n}\n\ntype EndpointTiming = { method: string; path: string; timing: number; sectionTimings: SectionTiming[] }\n\n/**\n * Number of uncached files at or below which analysis runs inline on the (already-warm) main-thread\n * Project instead of fanning out to worker threads. Each worker pays a multi-second cold-start to\n * build its own Project, so parallelism only wins once there are several files to share that cost.\n */\nconst INLINE_ANALYSIS_FILE_THRESHOLD = 2\n\n/**\n * @param tsconfigPath Path to tsconfig file relative to project root\n * @param sourceFilePaths Array of router source files relative to project root\n */\nexport const prepareOpenApiSpec = async ({\n\tlogLevel,\n\ttsconfigPath,\n\tsourceFilePaths,\n\tsourceFileDiscovery,\n\tincremental,\n\tprofiling = 'stats',\n\tworkers = false,\n}: Props): Promise<void> => {\n\tconst openApiManager = OpenApiManager.getInstance()\n\n\tif (openApiManager.isReady()) {\n\t\treturn\n\t}\n\n\tif (logLevel) {\n\t\tLogger.setLevel(logLevel)\n\t}\n\n\tLogger.info('Preparing OpenAPI spec')\n\n\tconst project = new Project({\n\t\ttsConfigFilePath: path.resolve(tsconfigPath),\n\t\tskipFileDependencyResolution: true,\n\t})\n\n\tconst { explicitRouters, discoveredRouterFiles, allSourceFiles } = (() => {\n\t\tconst sourceFilesToAdd = sourceFilePaths ?? []\n\t\tconst resolvedSourceFilePaths = sourceFilesToAdd.map((filepath) => path.resolve(filepath))\n\t\tconst sourceFiles = resolvedSourceFilePaths.map((filePath) => project.getSourceFileOrThrow(filePath))\n\t\tconst explicitRouters = sourceFiles.flatMap((file) => ({\n\t\t\tfileName: file.getFilePath(),\n\t\t\tsourceFile: file,\n\t\t\trouters: discoverRouters(file),\n\t\t}))\n\n\t\tconst { discoveredRouterFiles, discoveredSourceFiles } = (() => {\n\t\t\tif (sourceFileDiscovery === false) {\n\t\t\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t\t\t}\n\n\t\t\tconst startTime = performance.now()\n\t\t\tconst files = discoverRouterFiles({\n\t\t\t\ttargetPath: typeof sourceFileDiscovery === 'object' ? sourceFileDiscovery.rootPath : '.',\n\t\t\t\tproject,\n\t\t\t})\n\t\t\tif (profiling !== 'off') {\n\t\t\t\tLogger.info(`File discovery took ${Math.round(performance.now() - startTime)}ms`)\n\t\t\t}\n\t\t\treturn files\n\t\t})()\n\n\t\tconst allSourceFiles = sourceFiles.reduce(\n\t\t\t(acc, current) =>\n\t\t\t\tacc.some((r) => r.getFilePath() === current.getFilePath()) ? acc : acc.concat(current),\n\t\t\tdiscoveredSourceFiles,\n\t\t)\n\n\t\treturn { explicitRouters, discoveredRouterFiles, allSourceFiles }\n\t})()\n\n\tconst filesToAnalyze = explicitRouters.reduce(\n\t\t(acc, current) => (acc.some((r) => r.fileName === current.fileName) ? acc : acc.concat(current)),\n\t\tdiscoveredRouterFiles,\n\t)\n\n\tconst apiHeaders = allSourceFiles\n\t\t.flatMap((file) => analyzeSourceFileApiHeader(file))\n\t\t.filter((headers) => !!headers)\n\tif (apiHeaders.length > 0 && apiHeaders[0]) {\n\t\topenApiManager.setHeader(apiHeaders[0])\n\t}\n\n\tconst exposedModels = allSourceFiles.flatMap((file) => analyzeSourceFileExposedModels(file))\n\n\topenApiManager.setExposedModels(exposedModels)\n\n\tconst cachePath = (() => {\n\t\tif (typeof incremental === 'object' && incremental.cachePath) {\n\t\t\treturn incremental.cachePath\n\t\t}\n\t\treturn path.resolve(process.cwd(), 'node_modules', '.cache', 'moonflower')\n\t})()\n\tconst endpoints = await analyzeMultipleSourceFiles(filesToAnalyze, {\n\t\tincremental: incremental !== false,\n\t\tcachePath,\n\t\ttimestampCache: {},\n\t\tprofiling,\n\t\ttsconfigPath: path.resolve(tsconfigPath),\n\t\tworkers,\n\t})\n\n\topenApiManager.setStats({\n\t\tdiscoveredRouterFiles: discoveredRouterFiles.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t\texplicitRouterFiles: explicitRouters.map((file) => ({\n\t\t\tpath: file.fileName,\n\t\t\trouters: file.routers.named.map((r) => ({\n\t\t\t\tname: r,\n\t\t\t\tendpoints: endpoints\n\t\t\t\t\t.filter((e) => e.sourceFilePath === file.fileName)\n\t\t\t\t\t.map((e) => `${e.method.toUpperCase()} ${e.path}`),\n\t\t\t})),\n\t\t})),\n\t})\n\n\topenApiManager.setEndpoints(endpoints)\n\topenApiManager.markAsReady()\n}\n\nexport const analyzeMultipleSourceFiles = async (\n\tfiles: DiscoveredSourceFile[],\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t\ttsconfigPath: string\n\t\tworkers?: boolean\n\t},\n\tfilterEndpointPaths?: string[],\n): Promise<EndpointData[]> => {\n\tconst profiling = config.profiling ?? 'stats'\n\tconst startTime = performance.now()\n\n\t// Separate cached files from those needing analysis\n\ttype CachedFile = { endpoints: EndpointData[]; fileName: string; timing: 0; endpointTimings: [] }\n\ttype UncachedFile = { file: DiscoveredSourceFile; timestamp: number }\n\n\tconst cached: CachedFile[] = []\n\tconst uncached: UncachedFile[] = []\n\n\tconst freshnessCheckStart = performance.now()\n\tconst mtimeCache: MtimeCache = new Map()\n\tfor (const file of files) {\n\t\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache, mtimeCache)\n\t\tconst hit = config.incremental\n\t\t\t? SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\t\t\t: null\n\t\tif (hit) {\n\t\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\t\tcached.push({ endpoints: hit.endpoints, fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t\t} else {\n\t\t\tuncached.push({ file, timestamp })\n\t\t}\n\t}\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Cache freshness check took ${Math.round(performance.now() - freshnessCheckStart)}ms`)\n\t}\n\n\tif (uncached.length === 0) {\n\t\tif (profiling !== 'off') {\n\t\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t\t}\n\t\treturn cached.flatMap((f) => f.endpoints)\n\t}\n\n\ttype FileResult = {\n\t\tendpoints: EndpointData[]\n\t\tfileName: string\n\t\ttiming: number\n\t\tendpointTimings: EndpointTiming[]\n\t}\n\n\tconst byFile = new Map<string, FileResult>()\n\tfor (const { file } of uncached) {\n\t\tbyFile.set(file.fileName, { endpoints: [], fileName: file.fileName, timing: 0, endpointTimings: [] })\n\t}\n\n\tconst useWorkers = config.workers !== false\n\tif (!useWorkers || uncached.length <= INLINE_ANALYSIS_FILE_THRESHOLD) {\n\t\tfor (const { file } of uncached) {\n\t\t\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\t\t\tconst fileResult = byFile.get(file.fileName)!\n\t\t\tfileResult.endpoints = endpoints\n\t\t\tfileResult.endpointTimings = endpointTimings\n\t\t\tfileResult.timing = endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t} else {\n\t\ttype FileTask = { task: WorkerTask; fileName: string }\n\t\tconst allTasks: FileTask[] = uncached.map(({ file }) => ({\n\t\t\tfileName: file.fileName,\n\t\t\ttask: {\n\t\t\t\ttaskId: crypto.randomUUID(),\n\t\t\t\ttsconfigPath: config.tsconfigPath,\n\t\t\t\tsourceFilePath: file.sourceFile.getFilePath(),\n\t\t\t\trouterNames: file.routers.named,\n\t\t\t\tfilterEndpointPaths,\n\t\t\t},\n\t\t}))\n\n\t\tconst pool = new WorkerPool(resolveWorkerUrl(), allTasks.length)\n\t\tlet results: WorkerResult[]\n\t\ttry {\n\t\t\tresults = await pool.runAll(allTasks.map((ft) => ft.task))\n\t\t} finally {\n\t\t\tpool.terminate()\n\t\t}\n\n\t\t// Each result maps 1:1 to a file task.\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst result = results[i]\n\t\t\tconst fileName = allTasks[i].fileName\n\t\t\tconst fileResult = byFile.get(fileName)!\n\n\t\t\tif ('error' in result) {\n\t\t\t\tLogger.error(`[${fileName}] Worker error: ${result.error}`)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfileResult.endpoints = result.endpoints\n\t\t\tfileResult.endpointTimings = result.endpointTimings\n\t\t\tfileResult.timing = result.endpointTimings.reduce((sum, t) => sum + t.timing, 0)\n\t\t}\n\t}\n\n\t// Write cache for each uncached file\n\tfor (const { file, timestamp } of uncached) {\n\t\tconst fileResult = byFile.get(file.fileName)!\n\t\tif (fileResult.endpoints.length > 0) {\n\t\t\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, fileResult.endpoints)\n\t\t}\n\t}\n\n\tconst analyzedFiles = [...cached, ...Array.from(byFile.values())]\n\n\tif (profiling !== 'off') {\n\t\tLogger.info(`Router analysis took ${Math.round(performance.now() - startTime)}ms`)\n\t}\n\n\tif (profiling === 'stats') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.filter((t) => t.timeTaken > 500)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t})\n\t} else if (profiling === 'debug') {\n\t\tanalyzedFiles\n\t\t\t.map((f) => ({ fileName: f.fileName, timeTaken: f.timing, endpointTimings: f.endpointTimings }))\n\t\t\t.sort((a, b) => b.timeTaken - a.timeTaken)\n\t\t\t.forEach((t) => {\n\t\t\t\tLogger.info(`- [${t.fileName}] Took ${Math.round(t.timeTaken)}ms to analyze`)\n\t\t\t\tt.endpointTimings\n\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t.forEach((ep) => {\n\t\t\t\t\t\tLogger.info(` - ${ep.method} ${ep.path} (${Math.round(ep.timing)}ms)`)\n\t\t\t\t\t\tep.sectionTimings\n\t\t\t\t\t\t\t.filter((s) => s.timing >= 1)\n\t\t\t\t\t\t\t.sort((a, b) => b.timing - a.timing)\n\t\t\t\t\t\t\t.forEach((s) => {\n\t\t\t\t\t\t\t\tLogger.info(` - ${s.section}: ${Math.round(s.timing)}ms`)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t})\n\t}\n\n\treturn analyzedFiles.flatMap((f) => f.endpoints)\n}\n\nexport const analyzeSourceFileWithCache = (\n\tfile: DiscoveredSourceFile,\n\tconfig: {\n\t\tincremental: boolean\n\t\tcachePath: string\n\t\ttimestampCache: TimestampCache\n\t\tprofiling?: 'stats' | 'off' | 'debug'\n\t},\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; timing: number; endpointTimings: EndpointTiming[] } => {\n\tconst timestamp = getSourceFileTimestamp(file.sourceFile, config.timestampCache)\n\tconst cachedResults = SourceFileCache.getCachedResults(file.sourceFile, timestamp, config.cachePath)\n\n\tif (cachedResults) {\n\t\tLogger.debug(`[${file.fileName}] Found cached results`)\n\t\treturn { endpoints: cachedResults.endpoints, timing: 0, endpointTimings: [] }\n\t}\n\tLogger.debug(`[${file.fileName}] Analyzing...`)\n\n\tconst t1 = performance.now()\n\tconst { endpoints, endpointTimings } = analyzeSourceFileEndpoints(file, filterEndpointPaths)\n\tconst t2 = performance.now()\n\tLogger.debug(`[${file.fileName}] Analyzed in ${t2 - t1}ms`)\n\tSourceFileCache.cacheResults(file.sourceFile, timestamp, config.cachePath, endpoints)\n\treturn { endpoints, timing: t2 - t1, endpointTimings }\n}\n\nexport const analyzeSourceFileEndpoints = (\n\tfile: DiscoveredSourceFile,\n\tfilterEndpointPaths?: string[],\n): { endpoints: EndpointData[]; endpointTimings: EndpointTiming[] } => {\n\tconst endpoints: EndpointData[] = []\n\tconst endpointTimings: EndpointTiming[] = []\n\tconst operations = ['get', 'post', 'put', 'delete', 'del', 'patch']\n\tconst joinedOperations = operations.join('|')\n\n\tfile.routers.named.forEach((routerName) => {\n\t\tconst routerPattern = new RegExp(`${routerName}\\\\.(?:${joinedOperations})`)\n\t\tfile.sourceFile.forEachChild((node) => {\n\t\t\tconst nodeText = node.getText()\n\n\t\t\tif (routerPattern.test(nodeText)) {\n\t\t\t\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\t\t\t\tif (filterEndpointPaths && !filterEndpointPaths.some((path) => endpointPath.includes(path))) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst t1 = performance.now()\n\t\t\t\tconst { endpoint, sectionTimings } = parseEndpoint(node, file.fileName)\n\t\t\t\tendpointTimings.push({\n\t\t\t\t\tmethod: endpoint.method,\n\t\t\t\t\tpath: endpoint.path,\n\t\t\t\t\ttiming: performance.now() - t1,\n\t\t\t\t\tsectionTimings,\n\t\t\t\t})\n\t\t\t\tendpoints.push(endpoint)\n\t\t\t}\n\t\t})\n\t})\n\n\treturn { endpoints, endpointTimings }\n}\n\nexport const analyzeSourceFileApiHeader = (sourceFile: SourceFile): ApiDocsHeader | null => {\n\tconst nameOfUseApiHeader = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useApiHeader',\n\t})\n\n\tif (!nameOfUseApiHeader) {\n\t\treturn null\n\t}\n\n\tconst node = sourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.find((node) => nameOfUseApiHeader && node.getText().startsWith(nameOfUseApiHeader))\n\n\tif (!node) {\n\t\treturn null\n\t}\n\n\tconst targetNode = node.getFirstDescendantByKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\tconst values = getValuesOfObjectLiteral(targetNode)\n\n\tconst collapseObject = (v: string | string[] | typeof values): any => {\n\t\tif (typeof v === 'string') {\n\t\t\treturn v\n\t\t}\n\t\tif (Array.isArray(v) && v.every((value) => typeof value === 'string')) {\n\t\t\treturn v\n\t\t}\n\n\t\treturn v.reduce((acc, current) => {\n\t\t\tif (typeof current === 'string') {\n\t\t\t\treturn acc\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[current.identifier]: collapseObject(current.value as string[]),\n\t\t\t}\n\t\t}, {})\n\t}\n\treturn collapseObject(values)\n}\n\nexport const analyzeSourceFileExposedModels = (sourceFile: SourceFile): ExposedModelData[] => {\n\tconst models: ExposedModelData[] = []\n\n\tconst nameOfUseExposeApiModel = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeApiModel',\n\t})\n\n\tconst nameOfUseExposeNamedApiModels = discoverImportedName({\n\t\tsourceFile,\n\t\toriginalName: 'useExposeNamedApiModels',\n\t})\n\n\tsourceFile\n\t\t.forEachChildAsArray()\n\t\t.filter((node) => node.isKind(SyntaxKind.ExpressionStatement))\n\t\t.map((node) => {\n\t\t\tif (nameOfUseExposeApiModel && node.getText().startsWith(nameOfUseExposeApiModel)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tmodels.push(parseExposedModel(firstChild))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (nameOfUseExposeNamedApiModels && node.getText().startsWith(nameOfUseExposeNamedApiModels)) {\n\t\t\t\tconst callExpressionNode = node.getFirstChild()\n\t\t\t\tconst syntaxListChildren = callExpressionNode?.getChildrenOfKind(SyntaxKind.SyntaxList) || []\n\n\t\t\t\tconst firstChild = syntaxListChildren[0].getFirstChild()\n\t\t\t\tif (!firstChild) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst parsedModels = parseNamedExposedModels(firstChild)\n\t\t\t\tparsedModels.forEach((model) => models.push(model))\n\t\t\t}\n\t\t})\n\treturn models\n}\n"],"names":["resolveWorkerUrl","candidates","candidate","url","existsSync","fileURLToPath","INLINE_ANALYSIS_FILE_THRESHOLD","prepareOpenApiSpec","logLevel","tsconfigPath","sourceFilePaths","sourceFileDiscovery","incremental","profiling","workers","openApiManager","OpenApiManager","Logger","project","Project","path","explicitRouters","discoveredRouterFiles","allSourceFiles","sourceFiles","filepath","filePath","file","discoverRouters","discoveredSourceFiles","startTime","files","discoverRouterFiles","acc","current","r","filesToAnalyze","apiHeaders","analyzeSourceFileApiHeader","headers","exposedModels","analyzeSourceFileExposedModels","cachePath","endpoints","analyzeMultipleSourceFiles","e","config","filterEndpointPaths","cached","uncached","freshnessCheckStart","mtimeCache","timestamp","getSourceFileTimestamp","hit","SourceFileCache","f","byFile","endpointTimings","analyzeSourceFileEndpoints","fileResult","sum","t","allTasks","crypto","pool","WorkerPool","results","ft","i","result","fileName","analyzedFiles","a","b","ep","joinedOperations","routerName","routerPattern","node","nodeText","resolveEndpointPath","t1","endpoint","sectionTimings","parseEndpoint","sourceFile","nameOfUseApiHeader","discoverImportedName","SyntaxKind","targetNode","values","getValuesOfObjectLiteral","collapseObject","v","value","models","nameOfUseExposeApiModel","nameOfUseExposeNamedApiModels","firstChild","parseExposedModel","parseNamedExposedModels","model"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const F=require("fs"),m=require("path"),g=require("ts-morph"),y=require("../discoverRouters/discoverRouters.cjs");function d(r){const s=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(s,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return s.default=r,Object.freeze(s)}const l=d(F),v=d(m),S=({targetPath:r,tsConfigPath:s,excludedFiles:t})=>{if(!l.existsSync(r))return{discoveredRouterFiles:[],discoveredSourceFiles:[]};const n=(t??[]).map(e=>typeof e=="string"?new RegExp(`${e}`):e),f=[/^node_modules/,/^\./,/^dist/,/\.d\.ts$/,/\.spec\.ts$/,/\.test\.ts$/].concat(n??[]),a=l.readdirSync(r,{recursive:!0}).filter(e=>!(typeof e!="string"||f.some(o=>o.test(e))||!e.endsWith(".ts"))),p=new g.Project({tsConfigFilePath:s,skipFileDependencyResolution:!0}),c=a.map(e=>{const o=v.resolve(r,e);return{fileName:e,sourceFile:p.getSourceFile(o)}}).filter(e=>!!e.sourceFile);return{discoveredRouterFiles:c.map(e=>{const{fileName:o,sourceFile:u}=e,i=y.discoverRouters(u);return i.named.length===0&&i.anonymous.length===0?null:{fileName:o,sourceFile:u,routers:i}}).filter(e=>e!==null),discoveredSourceFiles:c.map(e=>e.sourceFile)}};exports.discoverRouterFiles=S;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("fs"),p=require("path"),F=require("../discoverRouters/discoverRouters.cjs");function d(r){const s=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(s,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return s.default=r,Object.freeze(s)}const l=d(a),m=d(p),g=({targetPath:r,excludedFiles:s,project:t})=>{if(!l.existsSync(r))return{discoveredRouterFiles:[],discoveredSourceFiles:[]};const n=(s??[]).map(e=>typeof e=="string"?new RegExp(`${e}`):e),f=[/^node_modules/,/^\./,/^dist/,/\.d\.ts$/,/\.spec\.ts$/,/\.test\.ts$/].concat(n??[]),c=l.readdirSync(r,{recursive:!0}).filter(e=>!(typeof e!="string"||f.some(o=>o.test(e))||!e.endsWith(".ts"))).map(e=>{const o=m.resolve(r,e);return{fileName:e,sourceFile:t.getSourceFile(o)}}).filter(e=>!!e.sourceFile);return{discoveredRouterFiles:c.map(e=>{const{fileName:o,sourceFile:u}=e,i=F.discoverRouters(u);return i.named.length===0&&i.anonymous.length===0?null:{fileName:o,sourceFile:u,routers:i}}).filter(e=>e!==null),discoveredSourceFiles:c.map(e=>e.sourceFile)}};exports.discoverRouterFiles=g;
2
2
  //# sourceMappingURL=discoverRouterFiles.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"discoverRouterFiles.cjs","sources":["../../../../src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts"],"sourcesContent":["import * as fs from 'fs'\nimport * as path from 'path'\nimport { Project } from 'ts-morph'\n\nimport { discoverRouters } from '../discoverRouters/discoverRouters'\n\nexport type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['discoveredRouterFiles'][number]\n\nexport const discoverRouterFiles = ({\n\ttargetPath,\n\ttsConfigPath,\n\texcludedFiles,\n}: {\n\ttargetPath: string\n\ttsConfigPath: string\n\texcludedFiles?: (string | RegExp)[]\n}) => {\n\tif (!fs.existsSync(targetPath)) {\n\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t}\n\n\tconst usersExcludedFiles = (excludedFiles ?? []).map((value) =>\n\t\ttypeof value === 'string' ? new RegExp(`${value}`) : value,\n\t)\n\tconst excludedPrefixes = [/^node_modules/, /^\\./, /^dist/, /\\.d\\.ts$/, /\\.spec\\.ts$/, /\\.test\\.ts$/].concat(\n\t\tusersExcludedFiles ?? [],\n\t)\n\n\tconst files = fs.readdirSync(targetPath, { recursive: true }).filter((filePath): filePath is string => {\n\t\tif (typeof filePath !== 'string') {\n\t\t\treturn false\n\t\t}\n\n\t\tif (excludedPrefixes.some((p) => p.test(filePath))) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (!filePath.endsWith('.ts')) {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\tconst project = new Project({\n\t\ttsConfigFilePath: tsConfigPath,\n\t\tskipFileDependencyResolution: true,\n\t})\n\n\tconst allSourceFiles = files\n\t\t.map((fileName) => {\n\t\t\tconst filePath = path.resolve(targetPath, fileName)\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile: project.getSourceFile(filePath),\n\t\t\t}\n\t\t})\n\t\t.filter(\n\t\t\t(\n\t\t\t\tfile,\n\t\t\t): file is Omit<typeof file, 'sourceFile'> & { sourceFile: NonNullable<(typeof file)['sourceFile']> } =>\n\t\t\t\t!!file.sourceFile,\n\t\t)\n\n\tconst routersInFiles = allSourceFiles\n\t\t.map((file) => {\n\t\t\tconst { fileName, sourceFile } = file\n\t\t\tconst routers = discoverRouters(sourceFile)\n\t\t\tif (routers.named.length === 0 && routers.anonymous.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile,\n\t\t\t\trouters,\n\t\t\t}\n\t\t})\n\t\t.filter((file): file is NonNullable<typeof file> => file !== null)\n\treturn {\n\t\tdiscoveredRouterFiles: routersInFiles,\n\t\tdiscoveredSourceFiles: allSourceFiles.map((file) => file.sourceFile),\n\t}\n}\n"],"names":["discoverRouterFiles","targetPath","tsConfigPath","excludedFiles","fs","usersExcludedFiles","value","excludedPrefixes","files","filePath","p","project","Project","allSourceFiles","fileName","path","file","sourceFile","routers","discoverRouters"],"mappings":"meAQaA,EAAsB,CAAC,CACnC,WAAAC,EACA,aAAAC,EACA,cAAAC,CACD,IAIM,CACL,GAAI,CAACC,EAAG,WAAWH,CAAU,EAC5B,MAAO,CAAE,sBAAuB,GAAI,sBAAuB,CAAA,CAAG,EAGzD,MAAAI,GAAsBF,GAAiB,CAAA,GAAI,IAAKG,GACrD,OAAOA,GAAU,SAAW,IAAI,OAAO,GAAGA,CAAK,EAAE,EAAIA,CACtD,EACMC,EAAmB,CAAC,gBAAiB,MAAO,QAAS,WAAY,cAAe,aAAa,EAAE,OACpGF,GAAsB,CAAA,CACvB,EAEMG,EAAQJ,EAAG,YAAYH,EAAY,CAAE,UAAW,GAAM,EAAE,OAAQQ,GACjE,SAAOA,GAAa,UAIpBF,EAAiB,KAAMG,GAAMA,EAAE,KAAKD,CAAQ,CAAC,GAI7C,CAACA,EAAS,SAAS,KAAK,EAI5B,EAEKE,EAAU,IAAIC,UAAQ,CAC3B,iBAAkBV,EAClB,6BAA8B,EAAA,CAC9B,EAEKW,EAAiBL,EACrB,IAAKM,GAAa,CAClB,MAAML,EAAWM,EAAK,QAAQd,EAAYa,CAAQ,EAC3C,MAAA,CACN,SAAAA,EACA,WAAYH,EAAQ,cAAcF,CAAQ,CAC3C,CACA,CAAA,EACA,OAECO,GAEA,CAAC,CAACA,EAAK,UACT,EAgBM,MAAA,CACN,sBAfsBH,EACrB,IAAKG,GAAS,CACR,KAAA,CAAE,SAAAF,EAAU,WAAAG,CAAA,EAAeD,EAC3BE,EAAUC,kBAAgBF,CAAU,EAC1C,OAAIC,EAAQ,MAAM,SAAW,GAAKA,EAAQ,UAAU,SAAW,EACvD,KAED,CACN,SAAAJ,EACA,WAAAG,EACA,QAAAC,CACD,CACA,CAAA,EACA,OAAQF,GAA2CA,IAAS,IAAI,EAGjE,sBAAuBH,EAAe,IAAKG,GAASA,EAAK,UAAU,CACpE,CACD"}
1
+ {"version":3,"file":"discoverRouterFiles.cjs","sources":["../../../../src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts"],"sourcesContent":["import * as fs from 'fs'\nimport * as path from 'path'\nimport { Project } from 'ts-morph'\n\nimport { discoverRouters } from '../discoverRouters/discoverRouters'\n\nexport type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['discoveredRouterFiles'][number]\n\nexport const discoverRouterFiles = ({\n\ttargetPath,\n\texcludedFiles,\n\tproject,\n}: {\n\ttargetPath: string\n\texcludedFiles?: (string | RegExp)[]\n\tproject: Project\n}) => {\n\tif (!fs.existsSync(targetPath)) {\n\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t}\n\n\tconst usersExcludedFiles = (excludedFiles ?? []).map((value) =>\n\t\ttypeof value === 'string' ? new RegExp(`${value}`) : value,\n\t)\n\tconst excludedPrefixes = [/^node_modules/, /^\\./, /^dist/, /\\.d\\.ts$/, /\\.spec\\.ts$/, /\\.test\\.ts$/].concat(\n\t\tusersExcludedFiles ?? [],\n\t)\n\n\tconst files = fs.readdirSync(targetPath, { recursive: true }).filter((filePath): filePath is string => {\n\t\tif (typeof filePath !== 'string') {\n\t\t\treturn false\n\t\t}\n\n\t\tif (excludedPrefixes.some((p) => p.test(filePath))) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (!filePath.endsWith('.ts')) {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\tconst allSourceFiles = files\n\t\t.map((fileName) => {\n\t\t\tconst filePath = path.resolve(targetPath, fileName)\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile: project.getSourceFile(filePath),\n\t\t\t}\n\t\t})\n\t\t.filter(\n\t\t\t(\n\t\t\t\tfile,\n\t\t\t): file is Omit<typeof file, 'sourceFile'> & { sourceFile: NonNullable<(typeof file)['sourceFile']> } =>\n\t\t\t\t!!file.sourceFile,\n\t\t)\n\n\tconst routersInFiles = allSourceFiles\n\t\t.map((file) => {\n\t\t\tconst { fileName, sourceFile } = file\n\t\t\tconst routers = discoverRouters(sourceFile)\n\t\t\tif (routers.named.length === 0 && routers.anonymous.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile,\n\t\t\t\trouters,\n\t\t\t}\n\t\t})\n\t\t.filter((file): file is NonNullable<typeof file> => file !== null)\n\treturn {\n\t\tdiscoveredRouterFiles: routersInFiles,\n\t\tdiscoveredSourceFiles: allSourceFiles.map((file) => file.sourceFile),\n\t}\n}\n"],"names":["discoverRouterFiles","targetPath","excludedFiles","project","fs","usersExcludedFiles","value","excludedPrefixes","allSourceFiles","filePath","p","fileName","path","file","sourceFile","routers","discoverRouters"],"mappings":"6cAQaA,EAAsB,CAAC,CACnC,WAAAC,EACA,cAAAC,EACA,QAAAC,CACD,IAIM,CACL,GAAI,CAACC,EAAG,WAAWH,CAAU,EAC5B,MAAO,CAAE,sBAAuB,GAAI,sBAAuB,CAAA,CAAG,EAGzD,MAAAI,GAAsBH,GAAiB,CAAA,GAAI,IAAKI,GACrD,OAAOA,GAAU,SAAW,IAAI,OAAO,GAAGA,CAAK,EAAE,EAAIA,CACtD,EACMC,EAAmB,CAAC,gBAAiB,MAAO,QAAS,WAAY,cAAe,aAAa,EAAE,OACpGF,GAAsB,CAAA,CACvB,EAiBMG,EAfQJ,EAAG,YAAYH,EAAY,CAAE,UAAW,GAAM,EAAE,OAAQQ,GACjE,SAAOA,GAAa,UAIpBF,EAAiB,KAAMG,GAAMA,EAAE,KAAKD,CAAQ,CAAC,GAI7C,CAACA,EAAS,SAAS,KAAK,EAI5B,EAGC,IAAKE,GAAa,CAClB,MAAMF,EAAWG,EAAK,QAAQX,EAAYU,CAAQ,EAC3C,MAAA,CACN,SAAAA,EACA,WAAYR,EAAQ,cAAcM,CAAQ,CAC3C,CACA,CAAA,EACA,OAECI,GAEA,CAAC,CAACA,EAAK,UACT,EAgBM,MAAA,CACN,sBAfsBL,EACrB,IAAKK,GAAS,CACR,KAAA,CAAE,SAAAF,EAAU,WAAAG,CAAA,EAAeD,EAC3BE,EAAUC,kBAAgBF,CAAU,EAC1C,OAAIC,EAAQ,MAAM,SAAW,GAAKA,EAAQ,UAAU,SAAW,EACvD,KAED,CACN,SAAAJ,EACA,WAAAG,EACA,QAAAC,CACD,CACA,CAAA,EACA,OAAQF,GAA2CA,IAAS,IAAI,EAGjE,sBAAuBL,EAAe,IAAKK,GAASA,EAAK,UAAU,CACpE,CACD"}
@@ -1,8 +1,10 @@
1
+ import { Project } from 'ts-morph';
2
+
1
3
  export type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['discoveredRouterFiles'][number];
2
- export declare const discoverRouterFiles: ({ targetPath, tsConfigPath, excludedFiles, }: {
4
+ export declare const discoverRouterFiles: ({ targetPath, excludedFiles, project, }: {
3
5
  targetPath: string;
4
- tsConfigPath: string;
5
6
  excludedFiles?: (string | RegExp)[];
7
+ project: Project;
6
8
  }) => {
7
9
  discoveredRouterFiles: {
8
10
  fileName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"discoverRouterFiles.d.ts","sourceRoot":"","sources":["../../../../src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1G,eAAO,MAAM,mBAAmB,iDAI7B;IACF,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CACnC;;;;;;;;;;CAiEA,CAAA"}
1
+ {"version":3,"file":"discoverRouterFiles.d.ts","sourceRoot":"","sources":["../../../../src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAIlC,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1G,eAAO,MAAM,mBAAmB,4CAI7B;IACF,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IACnC,OAAO,EAAE,OAAO,CAAA;CAChB;;;;;;;;;;CA4DA,CAAA"}
@@ -1,11 +1,10 @@
1
1
  import * as n from "fs";
2
- import * as m from "path";
3
- import { Project as F } from "ts-morph";
4
- import { discoverRouters as a } from "../discoverRouters/discoverRouters.mjs";
5
- const R = ({
2
+ import * as f from "path";
3
+ import { discoverRouters as m } from "../discoverRouters/discoverRouters.mjs";
4
+ const v = ({
6
5
  targetPath: s,
7
- tsConfigPath: c,
8
- excludedFiles: u
6
+ excludedFiles: u,
7
+ project: c
9
8
  }) => {
10
9
  if (!n.existsSync(s))
11
10
  return { discoveredRouterFiles: [], discoveredSourceFiles: [] };
@@ -13,21 +12,18 @@ const R = ({
13
12
  (e) => typeof e == "string" ? new RegExp(`${e}`) : e
14
13
  ), d = [/^node_modules/, /^\./, /^dist/, /\.d\.ts$/, /\.spec\.ts$/, /\.test\.ts$/].concat(
15
14
  l ?? []
16
- ), f = n.readdirSync(s, { recursive: !0 }).filter((e) => !(typeof e != "string" || d.some((r) => r.test(e)) || !e.endsWith(".ts"))), p = new F({
17
- tsConfigFilePath: c,
18
- skipFileDependencyResolution: !0
19
- }), o = f.map((e) => {
20
- const r = m.resolve(s, e);
15
+ ), o = n.readdirSync(s, { recursive: !0 }).filter((e) => !(typeof e != "string" || d.some((r) => r.test(e)) || !e.endsWith(".ts"))).map((e) => {
16
+ const r = f.resolve(s, e);
21
17
  return {
22
18
  fileName: e,
23
- sourceFile: p.getSourceFile(r)
19
+ sourceFile: c.getSourceFile(r)
24
20
  };
25
21
  }).filter(
26
22
  (e) => !!e.sourceFile
27
23
  );
28
24
  return {
29
25
  discoveredRouterFiles: o.map((e) => {
30
- const { fileName: r, sourceFile: i } = e, t = a(i);
26
+ const { fileName: r, sourceFile: i } = e, t = m(i);
31
27
  return t.named.length === 0 && t.anonymous.length === 0 ? null : {
32
28
  fileName: r,
33
29
  sourceFile: i,
@@ -38,6 +34,6 @@ const R = ({
38
34
  };
39
35
  };
40
36
  export {
41
- R as discoverRouterFiles
37
+ v as discoverRouterFiles
42
38
  };
43
39
  //# sourceMappingURL=discoverRouterFiles.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"discoverRouterFiles.mjs","sources":["../../../../src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts"],"sourcesContent":["import * as fs from 'fs'\nimport * as path from 'path'\nimport { Project } from 'ts-morph'\n\nimport { discoverRouters } from '../discoverRouters/discoverRouters'\n\nexport type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['discoveredRouterFiles'][number]\n\nexport const discoverRouterFiles = ({\n\ttargetPath,\n\ttsConfigPath,\n\texcludedFiles,\n}: {\n\ttargetPath: string\n\ttsConfigPath: string\n\texcludedFiles?: (string | RegExp)[]\n}) => {\n\tif (!fs.existsSync(targetPath)) {\n\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t}\n\n\tconst usersExcludedFiles = (excludedFiles ?? []).map((value) =>\n\t\ttypeof value === 'string' ? new RegExp(`${value}`) : value,\n\t)\n\tconst excludedPrefixes = [/^node_modules/, /^\\./, /^dist/, /\\.d\\.ts$/, /\\.spec\\.ts$/, /\\.test\\.ts$/].concat(\n\t\tusersExcludedFiles ?? [],\n\t)\n\n\tconst files = fs.readdirSync(targetPath, { recursive: true }).filter((filePath): filePath is string => {\n\t\tif (typeof filePath !== 'string') {\n\t\t\treturn false\n\t\t}\n\n\t\tif (excludedPrefixes.some((p) => p.test(filePath))) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (!filePath.endsWith('.ts')) {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\tconst project = new Project({\n\t\ttsConfigFilePath: tsConfigPath,\n\t\tskipFileDependencyResolution: true,\n\t})\n\n\tconst allSourceFiles = files\n\t\t.map((fileName) => {\n\t\t\tconst filePath = path.resolve(targetPath, fileName)\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile: project.getSourceFile(filePath),\n\t\t\t}\n\t\t})\n\t\t.filter(\n\t\t\t(\n\t\t\t\tfile,\n\t\t\t): file is Omit<typeof file, 'sourceFile'> & { sourceFile: NonNullable<(typeof file)['sourceFile']> } =>\n\t\t\t\t!!file.sourceFile,\n\t\t)\n\n\tconst routersInFiles = allSourceFiles\n\t\t.map((file) => {\n\t\t\tconst { fileName, sourceFile } = file\n\t\t\tconst routers = discoverRouters(sourceFile)\n\t\t\tif (routers.named.length === 0 && routers.anonymous.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile,\n\t\t\t\trouters,\n\t\t\t}\n\t\t})\n\t\t.filter((file): file is NonNullable<typeof file> => file !== null)\n\treturn {\n\t\tdiscoveredRouterFiles: routersInFiles,\n\t\tdiscoveredSourceFiles: allSourceFiles.map((file) => file.sourceFile),\n\t}\n}\n"],"names":["discoverRouterFiles","targetPath","tsConfigPath","excludedFiles","fs","usersExcludedFiles","value","excludedPrefixes","files","filePath","p","project","Project","allSourceFiles","fileName","path","file","sourceFile","routers","discoverRouters"],"mappings":";;;;AAQO,MAAMA,IAAsB,CAAC;AAAA,EACnC,YAAAC;AAAA,EACA,cAAAC;AAAA,EACA,eAAAC;AACD,MAIM;AACL,MAAI,CAACC,EAAG,WAAWH,CAAU;AAC5B,WAAO,EAAE,uBAAuB,IAAI,uBAAuB,CAAA,EAAG;AAGzD,QAAAI,KAAsBF,KAAiB,CAAA,GAAI;AAAA,IAAI,CAACG,MACrD,OAAOA,KAAU,WAAW,IAAI,OAAO,GAAGA,CAAK,EAAE,IAAIA;AAAA,EACtD,GACMC,IAAmB,CAAC,iBAAiB,OAAO,SAAS,YAAY,eAAe,aAAa,EAAE;AAAA,IACpGF,KAAsB,CAAA;AAAA,EACvB,GAEMG,IAAQJ,EAAG,YAAYH,GAAY,EAAE,WAAW,IAAM,EAAE,OAAO,CAACQ,MACjE,SAAOA,KAAa,YAIpBF,EAAiB,KAAK,CAACG,MAAMA,EAAE,KAAKD,CAAQ,CAAC,KAI7C,CAACA,EAAS,SAAS,KAAK,EAI5B,GAEKE,IAAU,IAAIC,EAAQ;AAAA,IAC3B,kBAAkBV;AAAA,IAClB,8BAA8B;AAAA,EAAA,CAC9B,GAEKW,IAAiBL,EACrB,IAAI,CAACM,MAAa;AAClB,UAAML,IAAWM,EAAK,QAAQd,GAAYa,CAAQ;AAC3C,WAAA;AAAA,MACN,UAAAA;AAAA,MACA,YAAYH,EAAQ,cAAcF,CAAQ;AAAA,IAC3C;AAAA,EACA,CAAA,EACA;AAAA,IACA,CACCO,MAEA,CAAC,CAACA,EAAK;AAAA,EACT;AAgBM,SAAA;AAAA,IACN,uBAfsBH,EACrB,IAAI,CAACG,MAAS;AACR,YAAA,EAAE,UAAAF,GAAU,YAAAG,EAAA,IAAeD,GAC3BE,IAAUC,EAAgBF,CAAU;AAC1C,aAAIC,EAAQ,MAAM,WAAW,KAAKA,EAAQ,UAAU,WAAW,IACvD,OAED;AAAA,QACN,UAAAJ;AAAA,QACA,YAAAG;AAAA,QACA,SAAAC;AAAA,MACD;AAAA,IACA,CAAA,EACA,OAAO,CAACF,MAA2CA,MAAS,IAAI;AAAA,IAGjE,uBAAuBH,EAAe,IAAI,CAACG,MAASA,EAAK,UAAU;AAAA,EACpE;AACD;"}
1
+ {"version":3,"file":"discoverRouterFiles.mjs","sources":["../../../../src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts"],"sourcesContent":["import * as fs from 'fs'\nimport * as path from 'path'\nimport { Project } from 'ts-morph'\n\nimport { discoverRouters } from '../discoverRouters/discoverRouters'\n\nexport type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['discoveredRouterFiles'][number]\n\nexport const discoverRouterFiles = ({\n\ttargetPath,\n\texcludedFiles,\n\tproject,\n}: {\n\ttargetPath: string\n\texcludedFiles?: (string | RegExp)[]\n\tproject: Project\n}) => {\n\tif (!fs.existsSync(targetPath)) {\n\t\treturn { discoveredRouterFiles: [], discoveredSourceFiles: [] }\n\t}\n\n\tconst usersExcludedFiles = (excludedFiles ?? []).map((value) =>\n\t\ttypeof value === 'string' ? new RegExp(`${value}`) : value,\n\t)\n\tconst excludedPrefixes = [/^node_modules/, /^\\./, /^dist/, /\\.d\\.ts$/, /\\.spec\\.ts$/, /\\.test\\.ts$/].concat(\n\t\tusersExcludedFiles ?? [],\n\t)\n\n\tconst files = fs.readdirSync(targetPath, { recursive: true }).filter((filePath): filePath is string => {\n\t\tif (typeof filePath !== 'string') {\n\t\t\treturn false\n\t\t}\n\n\t\tif (excludedPrefixes.some((p) => p.test(filePath))) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (!filePath.endsWith('.ts')) {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\n\tconst allSourceFiles = files\n\t\t.map((fileName) => {\n\t\t\tconst filePath = path.resolve(targetPath, fileName)\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile: project.getSourceFile(filePath),\n\t\t\t}\n\t\t})\n\t\t.filter(\n\t\t\t(\n\t\t\t\tfile,\n\t\t\t): file is Omit<typeof file, 'sourceFile'> & { sourceFile: NonNullable<(typeof file)['sourceFile']> } =>\n\t\t\t\t!!file.sourceFile,\n\t\t)\n\n\tconst routersInFiles = allSourceFiles\n\t\t.map((file) => {\n\t\t\tconst { fileName, sourceFile } = file\n\t\t\tconst routers = discoverRouters(sourceFile)\n\t\t\tif (routers.named.length === 0 && routers.anonymous.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tfileName,\n\t\t\t\tsourceFile,\n\t\t\t\trouters,\n\t\t\t}\n\t\t})\n\t\t.filter((file): file is NonNullable<typeof file> => file !== null)\n\treturn {\n\t\tdiscoveredRouterFiles: routersInFiles,\n\t\tdiscoveredSourceFiles: allSourceFiles.map((file) => file.sourceFile),\n\t}\n}\n"],"names":["discoverRouterFiles","targetPath","excludedFiles","project","fs","usersExcludedFiles","value","excludedPrefixes","allSourceFiles","filePath","p","fileName","path","file","sourceFile","routers","discoverRouters"],"mappings":";;;AAQO,MAAMA,IAAsB,CAAC;AAAA,EACnC,YAAAC;AAAA,EACA,eAAAC;AAAA,EACA,SAAAC;AACD,MAIM;AACL,MAAI,CAACC,EAAG,WAAWH,CAAU;AAC5B,WAAO,EAAE,uBAAuB,IAAI,uBAAuB,CAAA,EAAG;AAGzD,QAAAI,KAAsBH,KAAiB,CAAA,GAAI;AAAA,IAAI,CAACI,MACrD,OAAOA,KAAU,WAAW,IAAI,OAAO,GAAGA,CAAK,EAAE,IAAIA;AAAA,EACtD,GACMC,IAAmB,CAAC,iBAAiB,OAAO,SAAS,YAAY,eAAe,aAAa,EAAE;AAAA,IACpGF,KAAsB,CAAA;AAAA,EACvB,GAiBMG,IAfQJ,EAAG,YAAYH,GAAY,EAAE,WAAW,IAAM,EAAE,OAAO,CAACQ,MACjE,SAAOA,KAAa,YAIpBF,EAAiB,KAAK,CAACG,MAAMA,EAAE,KAAKD,CAAQ,CAAC,KAI7C,CAACA,EAAS,SAAS,KAAK,EAI5B,EAGC,IAAI,CAACE,MAAa;AAClB,UAAMF,IAAWG,EAAK,QAAQX,GAAYU,CAAQ;AAC3C,WAAA;AAAA,MACN,UAAAA;AAAA,MACA,YAAYR,EAAQ,cAAcM,CAAQ;AAAA,IAC3C;AAAA,EACA,CAAA,EACA;AAAA,IACA,CACCI,MAEA,CAAC,CAACA,EAAK;AAAA,EACT;AAgBM,SAAA;AAAA,IACN,uBAfsBL,EACrB,IAAI,CAACK,MAAS;AACR,YAAA,EAAE,UAAAF,GAAU,YAAAG,EAAA,IAAeD,GAC3BE,IAAUC,EAAgBF,CAAU;AAC1C,aAAIC,EAAQ,MAAM,WAAW,KAAKA,EAAQ,UAAU,WAAW,IACvD,OAED;AAAA,QACN,UAAAJ;AAAA,QACA,YAAAG;AAAA,QACA,SAAAC;AAAA,MACD;AAAA,IACA,CAAA,EACA,OAAO,CAACF,MAA2CA,MAAS,IAAI;AAAA,IAGjE,uBAAuBL,EAAe,IAAI,CAACK,MAASA,EAAK,UAAU;AAAA,EACpE;AACD;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Router.cjs","sources":["../../src/router/Router.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport KoaRouter from '@koa/router'\nimport Koa from 'koa'\n\nimport { OpenApiManager } from '../openapi/manager/OpenApiManager'\nimport { ExtractedRequestParams } from '../utils/TypeUtils'\nimport { parseEndpointReturnValue } from './parseEndpointReturnValue'\n\ntype Props = {\n\tskipOpenApiAnalysis: boolean\n}\n\nexport class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {\n\tpublic koaRouter: KoaRouter = new KoaRouter()\n\n\tpublic constructor(props: Props = { skipOpenApiAnalysis: false }) {\n\t\tif (!props.skipOpenApiAnalysis) {\n\t\t\tconst openApiManager = OpenApiManager.getInstance()\n\t\t\topenApiManager.registerRouters([this])\n\t\t}\n\t}\n\n\tprivate async sendResponseValue<P extends string>(\n\t\tctx: Parameters<Parameters<KoaRouter['get']>[1]>[0],\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\t// @ts-ignore\n\t\tconst responseValue = await callback(ctx, undefined)\n\t\tconst { value, status, contentType } = parseEndpointReturnValue(responseValue)\n\t\tctx.body = value\n\t\tif (status !== 'unset') {\n\t\t\tctx.status = status\n\t\t}\n\t\tctx.set('Content-Type', contentType)\n\t}\n\n\tpublic use(...middleware: Array<KoaRouter.Middleware<StateT, ContextT>>) {\n\t\t// @ts-ignore\n\t\tthis.koaRouter.use(...middleware)\n\t\treturn this\n\t}\n\n\tpublic with<ResponseTypeT extends Record<string, any>>(\n\t\tmiddleware: (ctx: Koa.ParameterizedContext<ContextT>) => ResponseTypeT,\n\t) {\n\t\ttype AugmentedData = ResponseTypeT extends Promise<any> ? Awaited<ResponseTypeT> : ResponseTypeT\n\t\tthis.koaRouter.use(async (ctx, next) => {\n\t\t\t// @ts-ignore\n\t\t\tconst userData = await Promise.resolve(middleware(ctx))\n\t\t\tObject.keys(userData).forEach((key) => {\n\t\t\t\tctx[key] = userData[key]\n\t\t\t})\n\t\t\tawait next()\n\t\t})\n\t\treturn this as Router<StateT, ContextT & AugmentedData>\n\t}\n\n\tpublic get<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.get(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic post<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.post(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic put<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.put(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic delete<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.delete(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic del<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.del(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic patch<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.patch(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic routes() {\n\t\treturn this.koaRouter.routes()\n\t}\n\n\tpublic allowedMethods() {\n\t\treturn this.koaRouter.allowedMethods()\n\t}\n}\n"],"names":["Router","props","KoaRouter","OpenApiManager","ctx","callback","responseValue","value","status","contentType","parseEndpointReturnValue","middleware","next","userData","key","path"],"mappings":"8MAYO,MAAMA,CAAiE,CAGtE,YAAYC,EAAe,CAAE,oBAAqB,IAAS,CAF3D,KAAA,UAAuB,IAAIC,EAG5BD,EAAM,qBACaE,iBAAe,YAAY,EACnC,gBAAgB,CAAC,IAAI,CAAC,CACtC,CAGD,MAAc,kBACbC,EACAC,EACC,CAED,MAAMC,EAAgB,MAAMD,EAASD,EAAK,MAAS,EAC7C,CAAE,MAAAG,EAAO,OAAAC,EAAQ,YAAAC,CAAY,EAAIC,EAAAA,yBAAyBJ,CAAa,EAC7EF,EAAI,KAAOG,EACPC,IAAW,UACdJ,EAAI,OAASI,GAEVJ,EAAA,IAAI,eAAgBK,CAAW,CAAA,CAG7B,OAAOE,EAA2D,CAEnE,YAAA,UAAU,IAAI,GAAGA,CAAU,EACzB,IAAA,CAGD,KACNA,EACC,CAED,YAAK,UAAU,IAAI,MAAOP,EAAKQ,IAAS,CAEvC,MAAMC,EAAW,MAAM,QAAQ,QAAQF,EAAWP,CAAG,CAAC,EACtD,OAAO,KAAKS,CAAQ,EAAE,QAASC,GAAQ,CAClCV,EAAAU,CAAG,EAAID,EAASC,CAAG,CAAA,CACvB,EACD,MAAMF,EAAK,CAAA,CACX,EACM,IAAA,CAGD,IACNG,EACAV,EACC,CACD,YAAK,UAAU,IAAIU,EAAM,MAAOX,GAAQ,CACjC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,KACNU,EACAV,EACC,CACD,YAAK,UAAU,KAAKU,EAAM,MAAOX,GAAQ,CAClC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,IACNU,EACAV,EACC,CACD,YAAK,UAAU,IAAIU,EAAM,MAAOX,GAAQ,CACjC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,OACNU,EACAV,EACC,CACD,YAAK,UAAU,OAAOU,EAAM,MAAOX,GAAQ,CACpC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,IACNU,EACAV,EACC,CACD,YAAK,UAAU,IAAIU,EAAM,MAAOX,GAAQ,CACjC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,MACNU,EACAV,EACC,CACD,YAAK,UAAU,MAAMU,EAAM,MAAOX,GAAQ,CACnC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,QAAS,CACR,OAAA,KAAK,UAAU,OAAO,CAAA,CAGvB,gBAAiB,CAChB,OAAA,KAAK,UAAU,eAAe,CAAA,CAEvC"}
1
+ {"version":3,"file":"Router.cjs","sources":["../../src/router/Router.ts"],"sourcesContent":["import KoaRouter, { RouterContext, RouterMiddleware } from '@koa/router'\nimport Koa from 'koa'\n\nimport { OpenApiManager } from '../openapi/manager/OpenApiManager'\nimport { ExtractedRequestParams } from '../utils/TypeUtils'\nimport { parseEndpointReturnValue } from './parseEndpointReturnValue'\n\ntype Props = {\n\tskipOpenApiAnalysis: boolean\n}\n\nexport class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {\n\tpublic koaRouter: KoaRouter = new KoaRouter()\n\n\tpublic constructor(props: Props = { skipOpenApiAnalysis: false }) {\n\t\tif (!props.skipOpenApiAnalysis) {\n\t\t\tconst openApiManager = OpenApiManager.getInstance()\n\t\t\topenApiManager.registerRouters([this])\n\t\t}\n\t}\n\n\tprivate async sendResponseValue<P extends string>(\n\t\tctx: RouterContext,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\t// @ts-expect-error - Context is valid\n\t\tconst responseValue = await callback(ctx, undefined)\n\t\tconst { value, status, contentType } = parseEndpointReturnValue(responseValue)\n\t\tctx.body = value\n\t\tif (status !== 'unset') {\n\t\t\tctx.status = status\n\t\t}\n\t\tctx.set('Content-Type', contentType)\n\t}\n\n\tpublic use(...middleware: Array<RouterMiddleware<StateT, ContextT>>) {\n\t\tthis.koaRouter.use(...middleware)\n\t\treturn this\n\t}\n\n\tpublic with<ResponseTypeT extends Record<string, any>>(\n\t\tmiddleware: (ctx: Koa.ParameterizedContext<ContextT>) => ResponseTypeT,\n\t) {\n\t\ttype AugmentedData = ResponseTypeT extends Promise<any> ? Awaited<ResponseTypeT> : ResponseTypeT\n\t\tthis.koaRouter.use(async (ctx, next) => {\n\t\t\tconst userData = await Promise.resolve(middleware(ctx))\n\t\t\tObject.keys(userData).forEach((key) => {\n\t\t\t\tctx[key] = userData[key]\n\t\t\t})\n\t\t\tawait next()\n\t\t})\n\t\treturn this as Router<StateT, ContextT & AugmentedData>\n\t}\n\n\tpublic get<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.get(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic post<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.post(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic put<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.put(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic delete<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.delete(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic del<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.del(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic patch<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.patch(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic routes() {\n\t\treturn this.koaRouter.routes()\n\t}\n\n\tpublic allowedMethods() {\n\t\treturn this.koaRouter.allowedMethods()\n\t}\n}\n"],"names":["Router","props","KoaRouter","OpenApiManager","ctx","callback","responseValue","value","status","contentType","parseEndpointReturnValue","middleware","next","userData","key","path"],"mappings":"8MAWO,MAAMA,CAAiE,CAGtE,YAAYC,EAAe,CAAE,oBAAqB,IAAS,CAF3D,KAAA,UAAuB,IAAIC,EAG5BD,EAAM,qBACaE,iBAAe,YAAY,EACnC,gBAAgB,CAAC,IAAI,CAAC,CACtC,CAGD,MAAc,kBACbC,EACAC,EACC,CAED,MAAMC,EAAgB,MAAMD,EAASD,EAAK,MAAS,EAC7C,CAAE,MAAAG,EAAO,OAAAC,EAAQ,YAAAC,CAAY,EAAIC,EAAAA,yBAAyBJ,CAAa,EAC7EF,EAAI,KAAOG,EACPC,IAAW,UACdJ,EAAI,OAASI,GAEVJ,EAAA,IAAI,eAAgBK,CAAW,CAAA,CAG7B,OAAOE,EAAuD,CAC/D,YAAA,UAAU,IAAI,GAAGA,CAAU,EACzB,IAAA,CAGD,KACNA,EACC,CAED,YAAK,UAAU,IAAI,MAAOP,EAAKQ,IAAS,CACvC,MAAMC,EAAW,MAAM,QAAQ,QAAQF,EAAWP,CAAG,CAAC,EACtD,OAAO,KAAKS,CAAQ,EAAE,QAASC,GAAQ,CAClCV,EAAAU,CAAG,EAAID,EAASC,CAAG,CAAA,CACvB,EACD,MAAMF,EAAK,CAAA,CACX,EACM,IAAA,CAGD,IACNG,EACAV,EACC,CACD,YAAK,UAAU,IAAIU,EAAM,MAAOX,GAAQ,CACjC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,KACNU,EACAV,EACC,CACD,YAAK,UAAU,KAAKU,EAAM,MAAOX,GAAQ,CAClC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,IACNU,EACAV,EACC,CACD,YAAK,UAAU,IAAIU,EAAM,MAAOX,GAAQ,CACjC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,OACNU,EACAV,EACC,CACD,YAAK,UAAU,OAAOU,EAAM,MAAOX,GAAQ,CACpC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,IACNU,EACAV,EACC,CACD,YAAK,UAAU,IAAIU,EAAM,MAAOX,GAAQ,CACjC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,MACNU,EACAV,EACC,CACD,YAAK,UAAU,MAAMU,EAAM,MAAOX,GAAQ,CACnC,MAAA,KAAK,kBAAkBA,EAAKC,CAAQ,CAAA,CAC1C,EACM,IAAA,CAGD,QAAS,CACR,OAAA,KAAK,UAAU,OAAO,CAAA,CAGvB,gBAAiB,CAChB,OAAA,KAAK,UAAU,eAAe,CAAA,CAEvC"}
@@ -1,4 +1,4 @@
1
- import { default as KoaRouter } from '@koa/router';
1
+ import { default as KoaRouter, RouterMiddleware } from '@koa/router';
2
2
  import { default as Koa } from 'koa';
3
3
  import { ExtractedRequestParams } from '../utils/TypeUtils';
4
4
 
@@ -9,16 +9,23 @@ export declare class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultCon
9
9
  koaRouter: KoaRouter;
10
10
  constructor(props?: Props);
11
11
  private sendResponseValue;
12
- use(...middleware: Array<KoaRouter.Middleware<StateT, ContextT>>): this;
12
+ use(...middleware: Array<RouterMiddleware<StateT, ContextT>>): this;
13
13
  with<ResponseTypeT extends Record<string, any>>(middleware: (ctx: Koa.ParameterizedContext<ContextT>) => ResponseTypeT): Router<StateT, ContextT & (ResponseTypeT extends Promise<any> ? Awaited<ResponseTypeT> : ResponseTypeT)>;
14
- get<P extends string>(path: P, callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
15
- post<P extends string>(path: P, callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
16
- put<P extends string>(path: P, callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
17
- delete<P extends string>(path: P, callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
18
- del<P extends string>(path: P, callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
19
- patch<P extends string>(path: P, callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
20
- routes(): KoaRouter.Middleware<Koa.DefaultState, Koa.DefaultContext, unknown>;
21
- allowedMethods(): KoaRouter.Middleware<Koa.DefaultState, Koa.DefaultContext, unknown>;
14
+ get<P extends string>(path: P, callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
15
+ post<P extends string>(path: P, callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
16
+ put<P extends string>(path: P, callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
17
+ delete<P extends string>(path: P, callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
18
+ del<P extends string>(path: P, callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
19
+ patch<P extends string>(path: P, callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>): this;
20
+ routes(): Koa.Middleware<Koa.DefaultState, Koa.DefaultContext & {
21
+ params: Record<string, string>;
22
+ router: import('@koa/router').RouterInstance<Koa.DefaultState, Koa.DefaultContext>;
23
+ _matchedRoute?: string | RegExp;
24
+ _matchedRouteName?: string;
25
+ }> & {
26
+ router?: KoaRouter<Koa.DefaultState, Koa.DefaultContext> | undefined;
27
+ };
28
+ allowedMethods(): RouterMiddleware<Koa.DefaultState, Koa.DefaultContext, unknown>;
22
29
  }
23
30
  export {};
24
31
  //# sourceMappingURL=Router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/router/Router.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,aAAa,CAAA;AACnC,OAAO,GAAG,MAAM,KAAK,CAAA;AAGrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,KAAK,KAAK,GAAG;IACZ,mBAAmB,EAAE,OAAO,CAAA;CAC5B,CAAA;AAED,qBAAa,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,QAAQ,GAAG,GAAG,CAAC,cAAc;IACpE,SAAS,EAAE,SAAS,CAAkB;gBAE1B,KAAK,GAAE,KAAsC;YAOlD,iBAAiB;IAcxB,GAAG,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAMhE,IAAI,CAAC,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpD,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,aAAa,GAWvD,MAAM,CAAC,MAAM,EAAE,QAAQ,gFAAgB,CAAC;IAGjD,GAAG,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQtE,IAAI,CAAC,CAAC,SAAS,MAAM,EAC3B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQtE,GAAG,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQtE,MAAM,CAAC,CAAC,SAAS,MAAM,EAC7B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQtE,GAAG,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQtE,KAAK,CAAC,CAAC,SAAS,MAAM,EAC5B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQtE,MAAM;IAIN,cAAc;CAGrB"}
1
+ {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/router/Router.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAiB,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,GAAG,MAAM,KAAK,CAAA;AAGrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,KAAK,KAAK,GAAG;IACZ,mBAAmB,EAAE,OAAO,CAAA;CAC5B,CAAA;AAED,qBAAa,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,QAAQ,GAAG,GAAG,CAAC,cAAc;IACpE,SAAS,EAAE,SAAS,CAAkB;gBAE1B,KAAK,GAAE,KAAsC;YAOlD,iBAAiB;IAcxB,GAAG,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAK5D,IAAI,CAAC,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACpD,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,aAAa,GAUvD,MAAM,CAAC,MAAM,EAAE,QAAQ,gFAAgB,CAAC;IAGjD,GAAG,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQlE,IAAI,CAAC,CAAC,SAAS,MAAM,EAC3B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQlE,GAAG,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQlE,MAAM,CAAC,CAAC,SAAS,MAAM,EAC7B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQlE,GAAG,CAAC,CAAC,SAAS,MAAM,EAC1B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQlE,KAAK,CAAC,CAAC,SAAS,MAAM,EAC5B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAQlE,MAAM;;;;;;;;IAIN,cAAc;CAGrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Router.mjs","sources":["../../src/router/Router.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport KoaRouter from '@koa/router'\nimport Koa from 'koa'\n\nimport { OpenApiManager } from '../openapi/manager/OpenApiManager'\nimport { ExtractedRequestParams } from '../utils/TypeUtils'\nimport { parseEndpointReturnValue } from './parseEndpointReturnValue'\n\ntype Props = {\n\tskipOpenApiAnalysis: boolean\n}\n\nexport class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {\n\tpublic koaRouter: KoaRouter = new KoaRouter()\n\n\tpublic constructor(props: Props = { skipOpenApiAnalysis: false }) {\n\t\tif (!props.skipOpenApiAnalysis) {\n\t\t\tconst openApiManager = OpenApiManager.getInstance()\n\t\t\topenApiManager.registerRouters([this])\n\t\t}\n\t}\n\n\tprivate async sendResponseValue<P extends string>(\n\t\tctx: Parameters<Parameters<KoaRouter['get']>[1]>[0],\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\t// @ts-ignore\n\t\tconst responseValue = await callback(ctx, undefined)\n\t\tconst { value, status, contentType } = parseEndpointReturnValue(responseValue)\n\t\tctx.body = value\n\t\tif (status !== 'unset') {\n\t\t\tctx.status = status\n\t\t}\n\t\tctx.set('Content-Type', contentType)\n\t}\n\n\tpublic use(...middleware: Array<KoaRouter.Middleware<StateT, ContextT>>) {\n\t\t// @ts-ignore\n\t\tthis.koaRouter.use(...middleware)\n\t\treturn this\n\t}\n\n\tpublic with<ResponseTypeT extends Record<string, any>>(\n\t\tmiddleware: (ctx: Koa.ParameterizedContext<ContextT>) => ResponseTypeT,\n\t) {\n\t\ttype AugmentedData = ResponseTypeT extends Promise<any> ? Awaited<ResponseTypeT> : ResponseTypeT\n\t\tthis.koaRouter.use(async (ctx, next) => {\n\t\t\t// @ts-ignore\n\t\t\tconst userData = await Promise.resolve(middleware(ctx))\n\t\t\tObject.keys(userData).forEach((key) => {\n\t\t\t\tctx[key] = userData[key]\n\t\t\t})\n\t\t\tawait next()\n\t\t})\n\t\treturn this as Router<StateT, ContextT & AugmentedData>\n\t}\n\n\tpublic get<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.get(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic post<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.post(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic put<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.put(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic delete<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.delete(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic del<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.del(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic patch<P extends string>(\n\t\tpath: P,\n\t\tcallback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.patch(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic routes() {\n\t\treturn this.koaRouter.routes()\n\t}\n\n\tpublic allowedMethods() {\n\t\treturn this.koaRouter.allowedMethods()\n\t}\n}\n"],"names":["Router","props","KoaRouter","OpenApiManager","ctx","callback","responseValue","value","status","contentType","parseEndpointReturnValue","middleware","next","userData","key","path"],"mappings":";;;AAYO,MAAMA,EAAiE;AAAA,EAGtE,YAAYC,IAAe,EAAE,qBAAqB,MAAS;AAF3D,SAAA,YAAuB,IAAIC,EAAU,GAGtCD,EAAM,uBACaE,EAAe,YAAY,EACnC,gBAAgB,CAAC,IAAI,CAAC;AAAA,EACtC;AAAA,EAGD,MAAc,kBACbC,GACAC,GACC;AAED,UAAMC,IAAgB,MAAMD,EAASD,GAAK,MAAS,GAC7C,EAAE,OAAAG,GAAO,QAAAC,GAAQ,aAAAC,EAAY,IAAIC,EAAyBJ,CAAa;AAC7E,IAAAF,EAAI,OAAOG,GACPC,MAAW,YACdJ,EAAI,SAASI,IAEVJ,EAAA,IAAI,gBAAgBK,CAAW;AAAA,EAAA;AAAA,EAG7B,OAAOE,GAA2D;AAEnE,gBAAA,UAAU,IAAI,GAAGA,CAAU,GACzB;AAAA,EAAA;AAAA,EAGD,KACNA,GACC;AAED,gBAAK,UAAU,IAAI,OAAOP,GAAKQ,MAAS;AAEvC,YAAMC,IAAW,MAAM,QAAQ,QAAQF,EAAWP,CAAG,CAAC;AACtD,aAAO,KAAKS,CAAQ,EAAE,QAAQ,CAACC,MAAQ;AAClC,QAAAV,EAAAU,CAAG,IAAID,EAASC,CAAG;AAAA,MAAA,CACvB,GACD,MAAMF,EAAK;AAAA,IAAA,CACX,GACM;AAAA,EAAA;AAAA,EAGD,IACNG,GACAV,GACC;AACD,gBAAK,UAAU,IAAIU,GAAM,OAAOX,MAAQ;AACjC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,KACNU,GACAV,GACC;AACD,gBAAK,UAAU,KAAKU,GAAM,OAAOX,MAAQ;AAClC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,IACNU,GACAV,GACC;AACD,gBAAK,UAAU,IAAIU,GAAM,OAAOX,MAAQ;AACjC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,OACNU,GACAV,GACC;AACD,gBAAK,UAAU,OAAOU,GAAM,OAAOX,MAAQ;AACpC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,IACNU,GACAV,GACC;AACD,gBAAK,UAAU,IAAIU,GAAM,OAAOX,MAAQ;AACjC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,MACNU,GACAV,GACC;AACD,gBAAK,UAAU,MAAMU,GAAM,OAAOX,MAAQ;AACnC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,SAAS;AACR,WAAA,KAAK,UAAU,OAAO;AAAA,EAAA;AAAA,EAGvB,iBAAiB;AAChB,WAAA,KAAK,UAAU,eAAe;AAAA,EAAA;AAEvC;"}
1
+ {"version":3,"file":"Router.mjs","sources":["../../src/router/Router.ts"],"sourcesContent":["import KoaRouter, { RouterContext, RouterMiddleware } from '@koa/router'\nimport Koa from 'koa'\n\nimport { OpenApiManager } from '../openapi/manager/OpenApiManager'\nimport { ExtractedRequestParams } from '../utils/TypeUtils'\nimport { parseEndpointReturnValue } from './parseEndpointReturnValue'\n\ntype Props = {\n\tskipOpenApiAnalysis: boolean\n}\n\nexport class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {\n\tpublic koaRouter: KoaRouter = new KoaRouter()\n\n\tpublic constructor(props: Props = { skipOpenApiAnalysis: false }) {\n\t\tif (!props.skipOpenApiAnalysis) {\n\t\t\tconst openApiManager = OpenApiManager.getInstance()\n\t\t\topenApiManager.registerRouters([this])\n\t\t}\n\t}\n\n\tprivate async sendResponseValue<P extends string>(\n\t\tctx: RouterContext,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\t// @ts-expect-error - Context is valid\n\t\tconst responseValue = await callback(ctx, undefined)\n\t\tconst { value, status, contentType } = parseEndpointReturnValue(responseValue)\n\t\tctx.body = value\n\t\tif (status !== 'unset') {\n\t\t\tctx.status = status\n\t\t}\n\t\tctx.set('Content-Type', contentType)\n\t}\n\n\tpublic use(...middleware: Array<RouterMiddleware<StateT, ContextT>>) {\n\t\tthis.koaRouter.use(...middleware)\n\t\treturn this\n\t}\n\n\tpublic with<ResponseTypeT extends Record<string, any>>(\n\t\tmiddleware: (ctx: Koa.ParameterizedContext<ContextT>) => ResponseTypeT,\n\t) {\n\t\ttype AugmentedData = ResponseTypeT extends Promise<any> ? Awaited<ResponseTypeT> : ResponseTypeT\n\t\tthis.koaRouter.use(async (ctx, next) => {\n\t\t\tconst userData = await Promise.resolve(middleware(ctx))\n\t\t\tObject.keys(userData).forEach((key) => {\n\t\t\t\tctx[key] = userData[key]\n\t\t\t})\n\t\t\tawait next()\n\t\t})\n\t\treturn this as Router<StateT, ContextT & AugmentedData>\n\t}\n\n\tpublic get<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.get(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic post<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.post(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic put<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.put(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic delete<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.delete(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic del<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.del(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic patch<P extends string>(\n\t\tpath: P,\n\t\tcallback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,\n\t) {\n\t\tthis.koaRouter.patch(path, async (ctx) => {\n\t\t\tawait this.sendResponseValue(ctx, callback)\n\t\t})\n\t\treturn this\n\t}\n\n\tpublic routes() {\n\t\treturn this.koaRouter.routes()\n\t}\n\n\tpublic allowedMethods() {\n\t\treturn this.koaRouter.allowedMethods()\n\t}\n}\n"],"names":["Router","props","KoaRouter","OpenApiManager","ctx","callback","responseValue","value","status","contentType","parseEndpointReturnValue","middleware","next","userData","key","path"],"mappings":";;;AAWO,MAAMA,EAAiE;AAAA,EAGtE,YAAYC,IAAe,EAAE,qBAAqB,MAAS;AAF3D,SAAA,YAAuB,IAAIC,EAAU,GAGtCD,EAAM,uBACaE,EAAe,YAAY,EACnC,gBAAgB,CAAC,IAAI,CAAC;AAAA,EACtC;AAAA,EAGD,MAAc,kBACbC,GACAC,GACC;AAED,UAAMC,IAAgB,MAAMD,EAASD,GAAK,MAAS,GAC7C,EAAE,OAAAG,GAAO,QAAAC,GAAQ,aAAAC,EAAY,IAAIC,EAAyBJ,CAAa;AAC7E,IAAAF,EAAI,OAAOG,GACPC,MAAW,YACdJ,EAAI,SAASI,IAEVJ,EAAA,IAAI,gBAAgBK,CAAW;AAAA,EAAA;AAAA,EAG7B,OAAOE,GAAuD;AAC/D,gBAAA,UAAU,IAAI,GAAGA,CAAU,GACzB;AAAA,EAAA;AAAA,EAGD,KACNA,GACC;AAED,gBAAK,UAAU,IAAI,OAAOP,GAAKQ,MAAS;AACvC,YAAMC,IAAW,MAAM,QAAQ,QAAQF,EAAWP,CAAG,CAAC;AACtD,aAAO,KAAKS,CAAQ,EAAE,QAAQ,CAACC,MAAQ;AAClC,QAAAV,EAAAU,CAAG,IAAID,EAASC,CAAG;AAAA,MAAA,CACvB,GACD,MAAMF,EAAK;AAAA,IAAA,CACX,GACM;AAAA,EAAA;AAAA,EAGD,IACNG,GACAV,GACC;AACD,gBAAK,UAAU,IAAIU,GAAM,OAAOX,MAAQ;AACjC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,KACNU,GACAV,GACC;AACD,gBAAK,UAAU,KAAKU,GAAM,OAAOX,MAAQ;AAClC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,IACNU,GACAV,GACC;AACD,gBAAK,UAAU,IAAIU,GAAM,OAAOX,MAAQ;AACjC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,OACNU,GACAV,GACC;AACD,gBAAK,UAAU,OAAOU,GAAM,OAAOX,MAAQ;AACpC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,IACNU,GACAV,GACC;AACD,gBAAK,UAAU,IAAIU,GAAM,OAAOX,MAAQ;AACjC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,MACNU,GACAV,GACC;AACD,gBAAK,UAAU,MAAMU,GAAM,OAAOX,MAAQ;AACnC,YAAA,KAAK,kBAAkBA,GAAKC,CAAQ;AAAA,IAAA,CAC1C,GACM;AAAA,EAAA;AAAA,EAGD,SAAS;AACR,WAAA,KAAK,UAAU,OAAO;AAAA,EAAA;AAAA,EAGvB,iBAAiB;AAChB,WAAA,KAAK,UAAU,eAAe;AAAA,EAAA;AAEvC;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moonflower",
3
- "version": "1.5.4",
3
+ "version": "1.6.1",
4
4
  "description": "",
5
5
  "author": "tenebrie",
6
6
  "license": "MIT",
@@ -131,27 +131,23 @@
131
131
  "yargs": "^17.7.2"
132
132
  },
133
133
  "peerDependencies": {
134
- "@koa/router": "^13.1.1",
135
- "koa": "^3.2.0",
134
+ "@koa/router": "^15.0.0",
135
+ "koa": "^3.0.0",
136
136
  "koa-bodyparser": "^4.4.1",
137
137
  "ts-morph": "^28.0.0",
138
- "zod": "4.3.6"
138
+ "zod": "^4.0.0"
139
139
  },
140
140
  "peerDependenciesMeta": {
141
141
  "ts-morph": {
142
142
  "optional": true
143
- },
144
- "zod": {
145
- "optional": true
146
143
  }
147
144
  },
148
145
  "devDependencies": {
149
- "@koa/router": "^13.1.0",
146
+ "@koa/router": "^15.0.0",
150
147
  "@types/jest": "29.5.14",
151
148
  "@types/jsonwebtoken": "^9.0.7",
152
- "@types/koa": "^2.15.0",
149
+ "@types/koa": "^3.0.0",
153
150
  "@types/koa-bodyparser": "^4.3.12",
154
- "@types/koa__router": "^12.0.4",
155
151
  "@types/node": "^22.10.2",
156
152
  "@types/supertest": "^6.0.2",
157
153
  "@typescript-eslint/eslint-plugin": "^8.18.0",
@@ -162,15 +158,15 @@
162
158
  "eslint-plugin-simple-import-sort": "^12.1.1",
163
159
  "eslint-plugin-unused-imports": "^4.1.4",
164
160
  "jest": "29.7.0",
165
- "zod": "4.3.6",
166
- "koa": "^2.15.3",
161
+ "zod": "^4.0.0",
162
+ "koa": "^3.0.0",
167
163
  "koa-bodyparser": "^4.4.1",
168
164
  "node-mocks-http": "^1.16.2",
169
165
  "prettier": "^3.4.2",
170
166
  "source-map-support": "^0.5.20",
171
167
  "supertest": "^7.0.0",
172
168
  "ts-jest": "29.2.5",
173
- "ts-morph": "^24.0.0",
169
+ "ts-morph": "^28.0.0",
174
170
  "ts-node": "^10.9.2",
175
171
  "tsconfig-paths": "4.2.0",
176
172
  "typescript": "^5.7.2",
@@ -109,7 +109,7 @@ export const prepareOpenApiSpec = async ({
109
109
  const startTime = performance.now()
110
110
  const files = discoverRouterFiles({
111
111
  targetPath: typeof sourceFileDiscovery === 'object' ? sourceFileDiscovery.rootPath : '.',
112
- tsConfigPath: tsconfigPath,
112
+ project,
113
113
  })
114
114
  if (profiling !== 'off') {
115
115
  Logger.info(`File discovery took ${Math.round(performance.now() - startTime)}ms`)
@@ -1,12 +1,21 @@
1
1
  import { resolve } from 'path'
2
+ import { Project } from 'ts-morph'
3
+ import { beforeEach, describe, expect, it } from 'vitest'
2
4
 
3
5
  import { discoverRouterFiles } from './discoverRouterFiles'
4
6
 
5
7
  describe('discoverRouterFiles', () => {
8
+ let project: Project
9
+ beforeEach(() => {
10
+ project = new Project({
11
+ tsConfigFilePath: resolve('./tsconfig.json'),
12
+ skipFileDependencyResolution: true,
13
+ })
14
+ })
6
15
  it('discovers routers from folder correctly', () => {
7
16
  const { discoveredRouterFiles } = discoverRouterFiles({
8
17
  targetPath: resolve(__dirname, '.'),
9
- tsConfigPath: resolve('./tsconfig.json'),
18
+ project,
10
19
  })
11
20
 
12
21
  expect(discoveredRouterFiles.length).toEqual(2)
@@ -15,8 +24,8 @@ describe('discoverRouterFiles', () => {
15
24
  it('respects ignoring files by string', () => {
16
25
  const { discoveredRouterFiles } = discoverRouterFiles({
17
26
  targetPath: resolve(__dirname, '.'),
18
- tsConfigPath: resolve('./tsconfig.json'),
19
27
  excludedFiles: ['testRouterA'],
28
+ project,
20
29
  })
21
30
 
22
31
  expect(discoveredRouterFiles.length).toEqual(1)
@@ -26,8 +35,8 @@ describe('discoverRouterFiles', () => {
26
35
  it('respects ignoring files by regex', () => {
27
36
  const { discoveredRouterFiles } = discoverRouterFiles({
28
37
  targetPath: resolve(__dirname, '.'),
29
- tsConfigPath: resolve('./tsconfig.json'),
30
38
  excludedFiles: [/B/g],
39
+ project,
31
40
  })
32
41
 
33
42
  expect(discoveredRouterFiles.length).toEqual(1)
@@ -8,12 +8,12 @@ export type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['disco
8
8
 
9
9
  export const discoverRouterFiles = ({
10
10
  targetPath,
11
- tsConfigPath,
12
11
  excludedFiles,
12
+ project,
13
13
  }: {
14
14
  targetPath: string
15
- tsConfigPath: string
16
15
  excludedFiles?: (string | RegExp)[]
16
+ project: Project
17
17
  }) => {
18
18
  if (!fs.existsSync(targetPath)) {
19
19
  return { discoveredRouterFiles: [], discoveredSourceFiles: [] }
@@ -41,11 +41,6 @@ export const discoverRouterFiles = ({
41
41
  return true
42
42
  })
43
43
 
44
- const project = new Project({
45
- tsConfigFilePath: tsConfigPath,
46
- skipFileDependencyResolution: true,
47
- })
48
-
49
44
  const allSourceFiles = files
50
45
  .map((fileName) => {
51
46
  const filePath = path.resolve(targetPath, fileName)
@@ -1,5 +1,4 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
2
- import KoaRouter from '@koa/router'
1
+ import KoaRouter, { RouterContext, RouterMiddleware } from '@koa/router'
3
2
  import Koa from 'koa'
4
3
 
5
4
  import { OpenApiManager } from '../openapi/manager/OpenApiManager'
@@ -21,10 +20,10 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
21
20
  }
22
21
 
23
22
  private async sendResponseValue<P extends string>(
24
- ctx: Parameters<Parameters<KoaRouter['get']>[1]>[0],
25
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
23
+ ctx: RouterContext,
24
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
26
25
  ) {
27
- // @ts-ignore
26
+ // @ts-expect-error - Context is valid
28
27
  const responseValue = await callback(ctx, undefined)
29
28
  const { value, status, contentType } = parseEndpointReturnValue(responseValue)
30
29
  ctx.body = value
@@ -34,8 +33,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
34
33
  ctx.set('Content-Type', contentType)
35
34
  }
36
35
 
37
- public use(...middleware: Array<KoaRouter.Middleware<StateT, ContextT>>) {
38
- // @ts-ignore
36
+ public use(...middleware: Array<RouterMiddleware<StateT, ContextT>>) {
39
37
  this.koaRouter.use(...middleware)
40
38
  return this
41
39
  }
@@ -45,7 +43,6 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
45
43
  ) {
46
44
  type AugmentedData = ResponseTypeT extends Promise<any> ? Awaited<ResponseTypeT> : ResponseTypeT
47
45
  this.koaRouter.use(async (ctx, next) => {
48
- // @ts-ignore
49
46
  const userData = await Promise.resolve(middleware(ctx))
50
47
  Object.keys(userData).forEach((key) => {
51
48
  ctx[key] = userData[key]
@@ -57,7 +54,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
57
54
 
58
55
  public get<P extends string>(
59
56
  path: P,
60
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
57
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
61
58
  ) {
62
59
  this.koaRouter.get(path, async (ctx) => {
63
60
  await this.sendResponseValue(ctx, callback)
@@ -67,7 +64,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
67
64
 
68
65
  public post<P extends string>(
69
66
  path: P,
70
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
67
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
71
68
  ) {
72
69
  this.koaRouter.post(path, async (ctx) => {
73
70
  await this.sendResponseValue(ctx, callback)
@@ -77,7 +74,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
77
74
 
78
75
  public put<P extends string>(
79
76
  path: P,
80
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
77
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
81
78
  ) {
82
79
  this.koaRouter.put(path, async (ctx) => {
83
80
  await this.sendResponseValue(ctx, callback)
@@ -87,7 +84,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
87
84
 
88
85
  public delete<P extends string>(
89
86
  path: P,
90
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
87
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
91
88
  ) {
92
89
  this.koaRouter.delete(path, async (ctx) => {
93
90
  await this.sendResponseValue(ctx, callback)
@@ -97,7 +94,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
97
94
 
98
95
  public del<P extends string>(
99
96
  path: P,
100
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
97
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
101
98
  ) {
102
99
  this.koaRouter.del(path, async (ctx) => {
103
100
  await this.sendResponseValue(ctx, callback)
@@ -107,7 +104,7 @@ export class Router<StateT = Koa.DefaultState, ContextT = Koa.DefaultContext> {
107
104
 
108
105
  public patch<P extends string>(
109
106
  path: P,
110
- callback: KoaRouter.Middleware<StateT, ContextT & ExtractedRequestParams<P>>,
107
+ callback: RouterMiddleware<StateT, ContextT & ExtractedRequestParams<P>>,
111
108
  ) {
112
109
  this.koaRouter.patch(path, async (ctx) => {
113
110
  await this.sendResponseValue(ctx, callback)