1515 */
1616
1717import { spawn } from 'child_process' ;
18- import { readFileSync , writeFileSync , mkdirSync , rmSync , existsSync , readdirSync , copyFileSync } from 'fs' ;
18+ import { readFileSync , writeFileSync , mkdirSync , rmSync , existsSync , readdirSync , copyFileSync , statSync } from 'fs' ;
1919import { join , dirname } from 'path' ;
2020import { fileURLToPath } from 'url' ;
21+ import yaml from 'js-yaml' ;
22+
23+ /**
24+ * Recursively copy a directory
25+ */
26+ function copyDirRecursive ( src , dest ) {
27+ mkdirSync ( dest , { recursive : true } ) ;
28+ for ( const entry of readdirSync ( src ) ) {
29+ const srcPath = join ( src , entry ) ;
30+ const destPath = join ( dest , entry ) ;
31+ if ( statSync ( srcPath ) . isDirectory ( ) ) {
32+ copyDirRecursive ( srcPath , destPath ) ;
33+ } else {
34+ copyFileSync ( srcPath , destPath ) ;
35+ }
36+ }
37+ }
2138
2239const __filename = fileURLToPath ( import . meta. url ) ;
2340const __dirname = dirname ( __filename ) ;
@@ -185,23 +202,62 @@ async function main() {
185202 console . log ( ` Generated: ${ domain } ` ) ;
186203 }
187204
188- // Step 3: Create index.ts that re-exports all domains and search helpers
189- console . log ( '\n3. Creating index exports...' ) ;
205+ // Step 3: Copy resolved OpenAPI specs to package
206+ console . log ( '\n3. Copying OpenAPI specs...' ) ;
207+ const openapiDir = join ( outputDir , 'openapi' ) ;
208+ copyDirRecursive ( resolvedDir , openapiDir ) ;
209+ console . log ( ` Copied resolved specs to openapi/` ) ;
210+
211+ // Step 4: Extract JSON schemas from bundled specs
212+ console . log ( '\n4. Extracting JSON schemas...' ) ;
213+ const jsonSchemaDir = join ( outputDir , 'json-schema' ) ;
214+ for ( const file of specFiles ) {
215+ const domain = file . replace ( '.yaml' , '' ) ;
216+ const specPath = join ( resolvedDir , file ) ;
217+ const domainBundled = join ( outputDir , `${ domain } -bundled.yaml` ) ;
218+ const domainSchemaDir = join ( jsonSchemaDir , domain ) ;
219+
220+ // Bundle spec (dereference $refs) for JSON schema extraction
221+ await exec ( 'npx' , [
222+ '@apidevtools/swagger-cli' , 'bundle' ,
223+ specPath ,
224+ '-o' , domainBundled ,
225+ '--dereference'
226+ ] ) ;
227+
228+ // Extract schemas from bundled spec
229+ const bundledContent = readFileSync ( domainBundled , 'utf8' ) ;
230+ const bundledSpec = yaml . load ( bundledContent ) ;
231+ const schemas = bundledSpec . components ?. schemas || { } ;
232+
233+ mkdirSync ( domainSchemaDir , { recursive : true } ) ;
234+ for ( const [ schemaName , schema ] of Object . entries ( schemas ) ) {
235+ const jsonSchemaPath = join ( domainSchemaDir , `${ schemaName } .json` ) ;
236+ writeFileSync ( jsonSchemaPath , JSON . stringify ( schema , null , 2 ) ) ;
237+ }
238+ console . log ( ` Extracted ${ Object . keys ( schemas ) . length } schemas for ${ domain } ` ) ;
239+
240+ // Clean up temp bundled file
241+ rmSync ( domainBundled , { force : true } ) ;
242+ }
243+
244+ // Step 5: Create index.ts that re-exports all domains and search helpers
245+ console . log ( '\n5. Creating index exports...' ) ;
190246 const domainExports = domains . map ( d => `export * as ${ d } from './${ d } /index.js';` ) . join ( '\n' ) ;
191247 const indexContent = `${ domainExports }
192248export { q, search } from './search-helpers.js';
193249` ;
194250 writeFileSync ( join ( srcDir , 'index.ts' ) , indexContent ) ;
195251 console . log ( ' Created index.ts' ) ;
196252
197- // Step 3b: Copy search helpers
253+ // Copy search helpers
198254 const searchHelpersSource = join ( templatesDir , 'search-helpers.ts' ) ;
199255 const searchHelpersDest = join ( srcDir , 'search-helpers.ts' ) ;
200256 copyFileSync ( searchHelpersSource , searchHelpersDest ) ;
201257 console . log ( ' Copied search-helpers.ts' ) ;
202258
203- // Step 4 : Generate package.json from template
204- console . log ( '\n4 . Generating package.json...' ) ;
259+ // Step 6 : Generate package.json from template
260+ console . log ( '\n6 . Generating package.json...' ) ;
205261 const packageTemplate = readFileSync ( join ( templatesDir , 'package.template.json' ) , 'utf8' ) ;
206262 const packageJson = packageTemplate
207263 . replace ( / \{ \{ S T A T E \} \} / g, state )
@@ -210,8 +266,8 @@ export { q, search } from './search-helpers.js';
210266 writeFileSync ( join ( outputDir , 'package.json' ) , packageJson ) ;
211267 console . log ( ' Generated package.json' ) ;
212268
213- // Step 5 : Create tsconfig for compilation
214- console . log ( '\n5 . Setting up TypeScript compilation...' ) ;
269+ // Step 7 : Create tsconfig for compilation
270+ console . log ( '\n7 . Setting up TypeScript compilation...' ) ;
215271 const tsconfig = {
216272 compilerOptions : {
217273 target : 'ES2020' ,
@@ -230,13 +286,13 @@ export { q, search } from './search-helpers.js';
230286 writeFileSync ( join ( outputDir , 'tsconfig.json' ) , JSON . stringify ( tsconfig , null , 2 ) ) ;
231287 console . log ( ' Created tsconfig.json' ) ;
232288
233- // Step 6 : Install build dependencies (peer deps needed for type checking)
234- console . log ( '\n6 . Installing build dependencies...' ) ;
289+ // Step 8 : Install build dependencies (peer deps needed for type checking)
290+ console . log ( '\n8 . Installing build dependencies...' ) ;
235291 await exec ( 'npm' , [ 'install' , 'zod@^4.3.5' , 'axios@^1.6.0' , '--save-dev' ] , { cwd : outputDir } ) ;
236292 console . log ( ' Dependencies installed' ) ;
237293
238- // Step 7 : Compile TypeScript
239- console . log ( '\n7 . Compiling TypeScript...' ) ;
294+ // Step 9 : Compile TypeScript
295+ console . log ( '\n9 . Compiling TypeScript...' ) ;
240296 try {
241297 await exec ( 'npx' , [ 'tsc' ] , { cwd : outputDir } ) ;
242298 } catch ( error ) {
0 commit comments