22
33const fs = require ( 'fs' ) ;
44const path = require ( 'path' ) ;
5+ const crypto = require ( 'crypto' ) ;
56const { getDir } = require ( './domainMapper' ) ;
6- const { generateEndpointMarkdown, AUTO_MARKER } = require ( './markdownGen' ) ;
7- const { mergeSummary } = require ( './summaryGen' ) ;
7+ const { generateEndpointMarkdown, AUTO_MARKER , resolveRef } = require ( './markdownGen' ) ;
8+ const { scanAndMergeSummary } = require ( './summaryGen' ) ;
9+
10+ const SNAPSHOT_FILE = '.openapi-snapshot.json' ;
11+ const METHODS = [ 'get' , 'post' , 'put' , 'patch' , 'delete' ] ;
12+
13+ function collectRefs ( obj , spec , depth , refs ) {
14+ if ( ! obj || typeof obj !== 'object' || depth > 3 ) return refs ;
15+
16+ if ( obj . $ref && ! refs [ obj . $ref ] ) {
17+ const resolved = resolveRef ( obj . $ref , spec ) ;
18+ if ( resolved ) {
19+ refs [ obj . $ref ] = resolved ;
20+ collectRefs ( resolved , spec , depth + 1 , refs ) ;
21+ }
22+ }
23+
24+ if ( Array . isArray ( obj ) ) {
25+ for ( const item of obj ) collectRefs ( item , spec , depth , refs ) ;
26+ } else {
27+ for ( const val of Object . values ( obj ) ) collectRefs ( val , spec , depth , refs ) ;
28+ }
29+
30+ return refs ;
31+ }
32+
33+ function computeHash ( operation , spec ) {
34+ const refs = collectRefs ( operation , spec , 0 , { } ) ;
35+ const input = JSON . stringify ( { operation, refs } ) ;
36+ return crypto . createHash ( 'md5' ) . update ( input ) . digest ( 'hex' ) ;
37+ }
838
939function generateFileName ( method , pathStr ) {
1040 const segments = pathStr
@@ -17,18 +47,51 @@ function generateFileName(method, pathStr) {
1747}
1848
1949function convert ( spec , outputDir ) {
20- const endpoints = [ ] ;
50+ const snapshotPath = path . join ( outputDir , SNAPSHOT_FILE ) ;
51+
52+ // Load previous snapshot (endpoint hash map)
53+ let prevHashes = null ;
54+ if ( fs . existsSync ( snapshotPath ) ) {
55+ try {
56+ prevHashes = JSON . parse ( fs . readFileSync ( snapshotPath , 'utf-8' ) ) ;
57+ } catch {
58+ prevHashes = null ;
59+ }
60+ }
61+
62+ // Build current hash map
63+ const currentHashes = { } ;
64+ for ( const [ pathStr , pathItem ] of Object . entries ( spec . paths || { } ) ) {
65+ for ( const method of METHODS ) {
66+ if ( ! pathItem [ method ] ) continue ;
67+ const key = `${ method . toUpperCase ( ) } ${ pathStr } ` ;
68+ currentHashes [ key ] = computeHash ( pathItem [ method ] , spec ) ;
69+ }
70+ }
71+
72+ // First run: save baseline, generate nothing
73+ if ( ! prevHashes ) {
74+ console . log ( 'No previous snapshot found. Saving baseline snapshot.' ) ;
75+ fs . mkdirSync ( outputDir , { recursive : true } ) ;
76+ fs . writeFileSync ( snapshotPath , JSON . stringify ( currentHashes , null , 2 ) , 'utf-8' ) ;
77+ return { filesWritten : 0 , skipped : 0 , domains : 0 } ;
78+ }
79+
80+ // Find new/changed endpoints
2181 let filesWritten = 0 ;
2282 let skipped = 0 ;
2383 const domainSet = new Set ( ) ;
2484
25- const methods = [ 'get' , 'post' , 'put' , 'patch' , 'delete' ] ;
26-
2785 for ( const [ pathStr , pathItem ] of Object . entries ( spec . paths || { } ) ) {
28- for ( const method of methods ) {
86+ for ( const method of METHODS ) {
2987 const operation = pathItem [ method ] ;
3088 if ( ! operation ) continue ;
3189
90+ const key = `${ method . toUpperCase ( ) } ${ pathStr } ` ;
91+
92+ // Skip unchanged endpoints
93+ if ( prevHashes [ key ] === currentHashes [ key ] ) continue ;
94+
3295 const tag = operation . tags ?. [ 0 ] || '기타' ;
3396 const dir = getDir ( tag ) ;
3497 domainSet . add ( dir ) ;
@@ -50,17 +113,14 @@ function convert(spec, outputDir) {
50113 fs . mkdirSync ( path . dirname ( filePath ) , { recursive : true } ) ;
51114 fs . writeFileSync ( filePath , markdown , 'utf-8' ) ;
52115 filesWritten ++ ;
53-
54- endpoints . push ( {
55- tag,
56- dir,
57- fileName,
58- title : operation . summary || `${ method . toUpperCase ( ) } ${ pathStr } ` ,
59- } ) ;
60116 }
61117 }
62118
63- mergeSummary ( outputDir , endpoints ) ;
119+ // Save updated snapshot
120+ fs . writeFileSync ( snapshotPath , JSON . stringify ( currentHashes , null , 2 ) , 'utf-8' ) ;
121+
122+ // Scan all auto-generated files and merge SUMMARY.md
123+ scanAndMergeSummary ( outputDir ) ;
64124
65125 return { filesWritten, skipped, domains : domainSet . size } ;
66126}
0 commit comments