1- import type { InputSchema , InternalRoute , TSchema } from 'elysia'
2- import {
3- readFileSync ,
4- mkdirSync ,
5- writeFileSync ,
6- rmSync ,
7- existsSync ,
8- readdirSync
9- } from 'fs'
101import { TypeBox } from '@sinclair/typemap'
11-
12- import { tmpdir } from 'os'
13- import { join } from 'path'
14- import { spawnSync } from 'child_process'
15- import { AdditionalReference } from '../types'
2+ import type { AdditionalReference } from '../types'
163
174const matchRoute = / : E l y s i a < ( .* ) > / gs
185const numberKey = / ( \d + ) : / g
196
20- interface OpenAPIGeneratorOptions {
7+ export interface OpenAPIGeneratorOptions {
218 /**
229 * Path to tsconfig.json
2310 * @default tsconfig.json
@@ -78,7 +65,12 @@ interface OpenAPIGeneratorOptions {
7865 silent ?: boolean
7966}
8067
81- function extractRootObjects ( code : string ) {
68+ /**
69+ * Polyfill path join for environments without Node.js path module
70+ */
71+ const join = ( ...parts : string [ ] ) => parts . join ( '/' ) . replace ( / \/ { 1 , } / g, '/' )
72+
73+ export function extractRootObjects ( code : string ) {
8274 const results = [ ]
8375 let i = 0
8476
@@ -183,24 +175,38 @@ export const fromTypes =
183175 *
184176 * The path must export an Elysia instance
185177 */
186- targetFilePath : string ,
178+ targetFilePath = 'src/index.ts' ,
187179 {
188180 tsconfigPath = 'tsconfig.json' ,
189181 instanceName,
190182 projectRoot = process . cwd ( ) ,
191183 overrideOutputPath,
192184 debug = false ,
193185 compilerOptions,
194- tmpRoot = join ( tmpdir ( ) , '.ElysiaAutoOpenAPI' ) ,
186+ tmpRoot,
195187 silent = false
196188 } : OpenAPIGeneratorOptions = { }
197189 ) =>
198190 ( ) => {
199- try {
200- // targetFilePath is an actual dts reference
201- if ( targetFilePath . trim ( ) . startsWith ( '{' ) )
202- return declarationToJSONSchema ( targetFilePath )
191+ // targetFilePath is an actual dts reference
192+ if ( targetFilePath . trim ( ) . startsWith ( '{' ) )
193+ return declarationToJSONSchema ( targetFilePath )
194+
195+ if (
196+ typeof process === 'undefined' ||
197+ typeof process . getBuiltinModule !== 'function'
198+ )
199+ throw new Error (
200+ '[@elysiajs/openapi/gen] `fromTypes` from file path is only available in Node.js/Bun environment or environments'
201+ )
202+
203+ const fs = process . getBuiltinModule ( 'fs' )
204+ if ( ! fs )
205+ throw new Error (
206+ '[@elysiajs/openapi/gen] `fromTypes` require `fs` module which is not available in this environment'
207+ )
203208
209+ try {
204210 if (
205211 ! targetFilePath . endsWith ( '.ts' ) &&
206212 ! targetFilePath . endsWith ( '.tsx' )
@@ -214,27 +220,38 @@ export const fromTypes =
214220 ? targetFilePath
215221 : join ( projectRoot , targetFilePath )
216222
217- if ( ! existsSync ( src ) )
223+ if ( ! fs . existsSync ( src ) )
218224 throw new Error (
219225 `Couldn't find "${ targetFilePath } " from ${ projectRoot } `
220226 )
221227
222228 let targetFile : string
223229
230+ if ( ! tmpRoot ) {
231+ const os = process . getBuiltinModule ( 'os' )
232+
233+ tmpRoot = join (
234+ os && typeof os . tmpdir === 'function'
235+ ? os . tmpdir ( )
236+ : projectRoot ,
237+ '.ElysiaAutoOpenAPI'
238+ )
239+ }
240+
224241 // Since it's already a declaration file
225242 // We can just read it directly
226243 if ( targetFilePath . endsWith ( '.d.ts' ) ) targetFile = targetFilePath
227244 else {
228- if ( existsSync ( tmpRoot ) )
229- rmSync ( tmpRoot , { recursive : true , force : true } )
245+ if ( fs . existsSync ( tmpRoot ) )
246+ fs . rmSync ( tmpRoot , { recursive : true , force : true } )
230247
231- mkdirSync ( tmpRoot , { recursive : true } )
248+ fs . mkdirSync ( tmpRoot , { recursive : true } )
232249
233250 const tsconfig = tsconfigPath . startsWith ( '/' )
234251 ? tsconfigPath
235252 : join ( projectRoot , tsconfigPath )
236253
237- let extendsRef = existsSync ( tsconfig )
254+ let extendsRef = fs . existsSync ( tsconfig )
238255 ? `"extends": "${ join ( projectRoot , 'tsconfig.json' ) } ",`
239256 : ''
240257
@@ -250,7 +267,7 @@ export const fromTypes =
250267 distDir = distDir . replace ( / \\ / g, '/' )
251268 }
252269
253- writeFileSync (
270+ fs . writeFileSync (
254271 join ( tmpRoot , 'tsconfig.json' ) ,
255272 `{
256273 ${ extendsRef }
@@ -273,6 +290,17 @@ export const fromTypes =
273290}`
274291 )
275292
293+ const child_process = process . getBuiltinModule ( 'child_process' )
294+ if ( ! child_process )
295+ throw new Error (
296+ '[@elysiajs/openapi/gen] `fromTypes` declaration generation require `child_process` module which is not available in this environment'
297+ )
298+ const { spawnSync } = child_process
299+ if ( typeof spawnSync !== 'function' )
300+ throw new Error (
301+ '[@elysiajs/openapi/gen] `fromTypes` declaration generation require child_process.spawnSync which is not available in this environment'
302+ )
303+
276304 spawnSync ( `tsc` , {
277305 shell : true ,
278306 cwd : tmpRoot ,
@@ -298,7 +326,7 @@ export const fromTypes =
298326 fileName . slice ( fileName . indexOf ( '/' ) + 1 )
299327 )
300328
301- let existed = existsSync ( targetFile )
329+ let existed = fs . existsSync ( targetFile )
302330
303331 if ( ! existed && ! overrideOutputPath ) {
304332 targetFile = join (
@@ -308,21 +336,22 @@ export const fromTypes =
308336 fileName
309337 )
310338
311- existed = existsSync ( targetFile )
339+ existed = fs . existsSync ( targetFile )
312340 }
313341
314342 if ( ! existed ) {
315- rmSync ( join ( tmpRoot , 'tsconfig.json' ) )
343+ fs . rmSync ( join ( tmpRoot , 'tsconfig.json' ) )
316344
317345 console . warn (
318346 '[@elysiajs/openapi/gen] Failed to generate OpenAPI schema'
319347 )
320348 console . warn ( "Couldn't find generated declaration file" )
321349
322- if ( existsSync ( join ( tmpRoot , 'dist' ) ) ) {
323- const tempFiles = readdirSync ( join ( tmpRoot , 'dist' ) , {
324- recursive : true
325- } )
350+ if ( fs . existsSync ( join ( tmpRoot , 'dist' ) ) ) {
351+ const tempFiles = fs
352+ . readdirSync ( join ( tmpRoot , 'dist' ) , {
353+ recursive : true
354+ } )
326355 . filter ( ( x ) => x . toString ( ) . endsWith ( '.d.ts' ) )
327356 . map ( ( x ) => `- ${ x } ` )
328357 . join ( '\n' )
@@ -344,11 +373,11 @@ export const fromTypes =
344373 }
345374 }
346375
347- const declaration = readFileSync ( targetFile , 'utf8' )
376+ const declaration = fs . readFileSync ( targetFile , 'utf8' )
348377
349378 // Check just in case of race-condition
350- if ( ! debug && existsSync ( tmpRoot ) )
351- rmSync ( tmpRoot , { recursive : true , force : true } )
379+ if ( ! debug && fs . existsSync ( tmpRoot ) )
380+ fs . rmSync ( tmpRoot , { recursive : true , force : true } )
352381
353382 let instance = declaration . match (
354383 instanceName
@@ -381,7 +410,7 @@ export const fromTypes =
381410
382411 return
383412 } finally {
384- if ( ! debug && existsSync ( tmpRoot ) )
385- rmSync ( tmpRoot , { recursive : true , force : true } )
413+ if ( ! debug && tmpRoot && fs . existsSync ( tmpRoot ) )
414+ fs . rmSync ( tmpRoot , { recursive : true , force : true } )
386415 }
387416 }
0 commit comments