11#!/usr/bin/env node
22
3+ import crypto from "crypto" ;
34import fs from "fs" ;
45import os from "os" ;
56import path from "path" ;
@@ -46,6 +47,7 @@ type DocsSyncOptions = {
4647 bindings : string [ ] ;
4748 dryRun ?: boolean ;
4849 noMermaid ?: boolean ;
50+ force ?: boolean ;
4951 help ?: boolean ;
5052} ;
5153
@@ -55,6 +57,7 @@ type DocsSyncMapping = {
5557 template_id ?: number ;
5658 source_files ?: string [ ] ;
5759 files ? : Record < string , number > ;
60+ file_hashes ? : Record < string , string > ;
5861 [ key : string ] : unknown ;
5962} ;
6063
@@ -362,6 +365,7 @@ function parseDocsSyncArgs(argv: string[]): DocsSyncOptions {
362365 if ( arg . startsWith ( "-- binding = ")) { options.bindings.push(arg.slice(10)); continue; }
363366 if (arg === " -- dry-run ") { options . dryRun = true ; continue ; }
364367 if ( arg = = = "--no-mermaid" ) { options . noMermaid = true ; continue ; }
368+ if ( arg = = = "--force" ) { options . force = true ; continue ; }
365369 if ( arg . startsWith ( "-" ) ) continue ;
366370 options . dirs . push ( arg ) ;
367371 }
@@ -428,6 +432,7 @@ function usage(): string {
428432 " --binding <name> use binding from .yapi/docs-sync.json (repeatable)" ,
429433 " --dry-run compute but do not update YApi or mapping files" ,
430434 " --no-mermaid do not render mermaid code blocks" ,
435+ " --force sync all files even if unchanged" ,
431436 "Docs-sync bind actions:" ,
432437 " list, get, add, update, remove" ,
433438 " -V, --version print version" ,
@@ -455,6 +460,7 @@ function docsSyncUsage(): string {
455460 " --binding <name> use binding from .yapi/docs-sync.json (repeatable)" ,
456461 " --dry-run compute but do not update YApi or mapping files" ,
457462 " --no-mermaid do not render mermaid code blocks" ,
463+ " --force sync all files even if unchanged" ,
458464 " -h, --help show help" ,
459465 ] . join ( "\n" ) ;
460466}
@@ -818,6 +824,13 @@ function saveMapping(mapping: DocsSyncMapping, mappingPath: string): void {
818824 fs . writeFileSync ( mappingPath , `${ JSON . stringify ( mapping , null , 2 ) } \n` , "utf8" ) ;
819825}
820826
827+ function buildDocsSyncHash ( markdown : string , options : DocsSyncOptions ) : string {
828+ const hash = crypto . createHash ( "sha1" ) ;
829+ hash . update ( options . noMermaid ? "no-mermaid\n" : "mermaid\n" ) ;
830+ hash . update ( markdown ) ;
831+ return hash . digest ( "hex" ) ;
832+ }
833+
821834function resolveSourceFiles ( dirPath : string , mapping : DocsSyncMapping ) : string [ ] {
822835 const sources = Array . isArray ( mapping . source_files ) ? mapping . source_files : [ ] ;
823836 if ( ! sources . length ) {
@@ -1014,8 +1027,13 @@ async function syncDocsDir(
10141027 mapping : DocsSyncMapping ,
10151028 options : DocsSyncOptions ,
10161029 request : YapiRequest ,
1017- ) : Promise < { updated : number ; created : number ; files : Record < string , DocsSyncFileInfo > } > {
1018- mapping . files = mapping . files || { } ;
1030+ ) : Promise < { updated : number ; created : number ; skipped : number ; files : Record < string , DocsSyncFileInfo > } > {
1031+ if ( ! mapping . files || typeof mapping . files !== "object" ) {
1032+ mapping . files = { } ;
1033+ }
1034+ if (!mapping.file_hashes || typeof mapping.file_hashes !== "object") {
1035+ mapping . file_hashes = { } ;
1036+ }
10191037
10201038 const envProjectId = process.env.YAPI_PROJECT_ID;
10211039 const envCatId = process.env.YAPI_CATID;
@@ -1032,6 +1050,7 @@ async function syncDocsDir(
10321050
10331051 let updated = 0;
10341052 let created = 0;
1053+ let skipped = 0;
10351054 const fileInfos: Record< string , DocsSyncFileInfo > = { } ;
10361055 const files = resolveSourceFiles(dirPath, mapping);
10371056 for (const mdPath of files) {
@@ -1059,6 +1078,13 @@ async function syncDocsDir(
10591078 }
10601079
10611080 const markdown = fs.readFileSync(mdPath, "utf8");
1081+ const contentHash = buildDocsSyncHash(markdown, options);
1082+ const previousHash = mapping.file_hashes[relName];
1083+ if (!options.force && docId && previousHash && previousHash === contentHash ) {
1084+ skipped += 1 ;
1085+ continue ;
1086+ }
1087+
10621088 const logPrefix = `[docs-sync:${ relName } ]`;
10631089 const html = renderMarkdownToHtml(markdown, {
10641090 noMermaid : options . noMermaid ,
@@ -1068,10 +1094,13 @@ async function syncDocsDir(
10681094 if (!options.dryRun && docId ) {
10691095 await updateInterface ( docId , markdown , html , request ) ;
10701096 }
1097+ if (docId) {
1098+ mapping . file_hashes [ relName ] = contentHash ;
1099+ }
10711100 updated += 1;
10721101 }
10731102
1074- return { updated , created , files : fileInfos } ;
1103+ return { updated , created , skipped , files : fileInfos } ;
10751104}
10761105
10771106function buildEnvUrls (
@@ -1267,6 +1296,7 @@ async function runDocsSyncBindings(rawArgs: string[]): Promise<number> {
12671296 template_id : existing . template_id ,
12681297 source_files : existing . source_files ? [ ...existing . source_files ] : undefined ,
12691298 files : existing . files ? { ...existing . files } : { } ,
1299+ file_hashes : existing . file_hashes ? { ...existing . file_hashes } : { } ,
12701300 } ;
12711301
12721302 if ( options . dir ) {
@@ -1499,7 +1529,9 @@ async function runDocsSync(rawArgs: string[]): Promise<number> {
14991529 }
15001530
15011531 const result = await syncDocsDir ( dirPath , binding , options , request ) ;
1502- console . log ( `synced=${ result . updated } created=${ result . created } binding=${ name } dir=${ dirPath } ` ) ;
1532+ console . log (
1533+ `synced=${ result . updated } created=${ result . created } skipped=${ result . skipped } binding=${ name } dir=${ dirPath } ` ,
1534+ ) ;
15031535 bindingResults [ name ] = { binding, files : result . files } ;
15041536 }
15051537
@@ -1521,7 +1553,7 @@ async function runDocsSync(rawArgs: string[]): Promise<number> {
15211553 saveMapping ( mapping , mappingPath ) ;
15221554 }
15231555
1524- console . log ( `synced=${ result . updated } created=${ result . created } dir=${ dirPath } ` ) ;
1556+ console . log ( `synced=${ result . updated } created=${ result . created } skipped= ${ result . skipped } dir=${ dirPath } ` ) ;
15251557 }
15261558 }
15271559
0 commit comments