1- // watch-cloud.mjs - Script to watch for changes in cloud-ts TypeScript files and compile them
1+ // watch-cloud.mjs - Simplified and efficient TypeScript file watcher and compiler
22import { exec } from 'child_process' ;
33import fs from 'fs/promises' ;
4- import { watch } from 'fs' ;
54import path from 'path' ;
65import { fileURLToPath } from 'url' ;
6+ import chokidar from 'chokidar' ;
7+ import ts from 'typescript' ;
78
8- // Get the current directory
99const __filename = fileURLToPath ( import . meta. url ) ;
1010const __dirname = path . dirname ( __filename ) ;
1111
12- // Compile all TypeScript files
12+ // Function to compile a single TypeScript file directly using transpileModule
13+ const compileSingleFile = async ( filePath ) => {
14+ try {
15+ console . log ( `Compiling file: ${ filePath } ` ) ;
16+
17+ const relativePath = path . relative ( path . join ( __dirname , 'cloud-ts' ) , filePath ) ;
18+ const outputPath = path . join ( __dirname , 'cloud' , relativePath . replace ( / \. t s $ / , '.js' ) ) ;
19+
20+ const tsContent = await fs . readFile ( filePath , 'utf8' ) ;
21+
22+ // Read and parse tsconfig.json
23+ const tsConfigPath = path . join ( __dirname , 'tsconfig.json' ) ;
24+ const tsConfigFile = ts . readConfigFile ( tsConfigPath , ts . sys . readFile ) ;
25+ const parsedConfig = ts . parseJsonConfigFileContent ( tsConfigFile . config , ts . sys , path . dirname ( tsConfigPath ) ) ;
26+
27+ // Transpile the TypeScript content
28+ const result = ts . transpileModule ( tsContent , { compilerOptions : parsedConfig . options , fileName : filePath } ) ;
29+
30+ // Ensure output directory exists
31+ await fs . mkdir ( path . dirname ( outputPath ) , { recursive : true } ) ;
32+
33+ // Write the transpiled JavaScript
34+ await fs . writeFile ( outputPath , result . outputText ) ;
35+
36+ console . log ( `Successfully compiled file: ${ filePath } ` ) ;
37+ } catch ( err ) {
38+ console . error ( `Error compiling file ${ filePath } : ${ err . message } ` ) ;
39+ throw err ;
40+ }
41+ } ;
42+
43+ // Full compilation for initial build or fallback
1344const compileAll = async ( ) => {
1445 return new Promise ( ( resolve , reject ) => {
1546 console . log ( 'Compiling all TypeScript files...' ) ;
16- const command = `npx tsc -p tsconfig.json` ;
17-
18- exec ( command , ( error , stdout , stderr ) => {
19- if ( stdout ) {
20- console . log ( stdout ) ;
21- }
22-
23- if ( stderr ) {
24- console . error ( `TypeScript compiler errors: ${ stderr } ` ) ;
25- }
26-
47+ exec ( `npx tsc --project tsconfig.json --incremental` , ( error , stdout , stderr ) => {
48+ if ( stdout ) console . log ( stdout ) ;
49+ if ( stderr ) console . error ( `TypeScript compiler errors: ${ stderr } ` ) ;
2750 if ( error ) {
2851 console . error ( `Error compiling: ${ error . message } ` ) ;
2952 return reject ( error ) ;
3053 }
31-
3254 console . log ( 'Successfully compiled all TypeScript files' ) ;
3355 resolve ( ) ;
3456 } ) ;
3557 } ) ;
3658} ;
3759
3860// Handle file deletion
39- const handleDeletion = async ( filename ) => {
40- if ( ! filename . endsWith ( '.ts' ) ) return ;
41-
42- // Get corresponding JS file path
43- const relativePath = filename ;
44- const jsFilePath = path . join ( 'cloud' , relativePath . replace ( '.ts' , '.js' ) ) ;
45-
61+ const handleDeletion = async ( filePath ) => {
62+ if ( ! filePath . endsWith ( '.ts' ) ) return ;
63+ const relativePath = path . relative ( path . join ( __dirname , 'cloud-ts' ) , filePath ) ;
64+ const jsFilePath = path . join ( __dirname , 'cloud' , relativePath . replace ( '.ts' , '.js' ) ) ;
65+
4666 try {
47- // Check if the JavaScript file exists
48- await fs . access ( jsFilePath ) ;
49-
50- // Delete the JavaScript file if it exists
5167 await fs . unlink ( jsFilePath ) ;
52- console . log ( `Deleted corresponding JavaScript file: ${ jsFilePath } ` ) ;
53-
54- // Handle .d.ts and .js.map files if they exist
55- const dtsFilePath = path . join ( 'cloud' , relativePath . replace ( '.ts' , '.d.ts' ) ) ;
56- const mapFilePath = path . join ( 'cloud' , relativePath . replace ( '.ts' , '.js.map' ) ) ;
57-
58- try {
59- await fs . access ( dtsFilePath ) ;
60- await fs . unlink ( dtsFilePath ) ;
61- console . log ( `Deleted declaration file: ${ dtsFilePath } ` ) ;
62- } catch ( err ) {
63- // File doesn't exist, ignore
64- }
65-
66- try {
67- await fs . access ( mapFilePath ) ;
68- await fs . unlink ( mapFilePath ) ;
69- console . log ( `Deleted source map file: ${ mapFilePath } ` ) ;
70- } catch ( err ) {
71- // File doesn't exist, ignore
72- }
68+ console . log ( `Deleted JavaScript file: ${ jsFilePath } ` ) ;
7369 } catch ( err ) {
74- // File doesn't exist or other error
75- console . log ( `Note: No JavaScript file found to delete for ${ filename } ` ) ;
70+ console . log ( `No JavaScript file found to delete for ${ relativePath } ` ) ;
7671 }
7772} ;
7873
79- // Watch for changes in the cloud-ts directory
74+ // Watch for changes
8075const watchForChanges = ( ) => {
81- // Ensure cloud directory exists
82- fs . mkdir ( 'cloud' , { recursive : true } )
83- . then ( ( ) => {
84- console . log ( 'Watching cloud-ts directory for changes and deletions...' ) ;
85-
86- // Track existing files in the cloud-ts directory
87- let knownFiles = new Set ( ) ;
88-
89- // Function to scan and update the list of known files
90- const updateKnownFiles = async ( ) => {
91- try {
92- const files = await fs . readdir ( 'cloud-ts' , { recursive : true } ) ;
93- const newKnownFiles = new Set ( ) ;
94-
95- for ( const file of files ) {
96- if ( file . endsWith ( '.ts' ) ) {
97- newKnownFiles . add ( file ) ;
98- }
99- }
100-
101- // Check for deletions
102- for ( const file of knownFiles ) {
103- if ( ! newKnownFiles . has ( file ) ) {
104- console . log ( `Detected deletion of: ${ file } ` ) ;
105- await handleDeletion ( file ) ;
106- }
107- }
108-
109- knownFiles = newKnownFiles ;
110- } catch ( err ) {
111- console . error ( `Error updating known files: ${ err . message } ` ) ;
112- }
113- } ;
114-
115- // Initial scan
116- updateKnownFiles ( ) ;
117-
118- // Watch the cloud-ts directory for changes
119- watch ( 'cloud-ts' , { recursive : true } , async ( eventType , filename ) => {
120- if ( ! filename ) return ;
121-
122- console . log ( `File event: ${ eventType } - ${ filename } ` ) ;
123-
124- // Scan for changes including deletions
125- await updateKnownFiles ( ) ;
126-
127- // Always recompile on any change
128- try {
129- await compileAll ( ) ;
130- } catch ( err ) {
131- console . error ( `Error compiling files: ${ err . message } ` ) ;
132- }
133- } ) ;
134-
135- // Periodically check for deleted files (as a backup)
136- setInterval ( updateKnownFiles , 5000 ) ;
137- } )
138- . catch ( err => {
139- console . error ( `Error setting up directory watch: ${ err . message } ` ) ;
140- process . exit ( 1 ) ;
141- } ) ;
76+ chokidar . watch ( 'cloud-ts' , { ignored : / ( ^ | [ \/ \\ ] ) \. ./ , persistent : true , ignoreInitial : true } )
77+ . on ( 'add' , compileSingleFile )
78+ . on ( 'change' , compileSingleFile )
79+ . on ( 'unlink' , handleDeletion )
80+ . on ( 'error' , error => console . error ( `Watcher error: ${ error } ` ) ) ;
81+
82+ console . log ( 'Watcher initialized. Monitoring cloud-ts directory for changes...' ) ;
14283} ;
14384
14485// Main function
14586const main = async ( ) => {
146- try {
147- // Ensure cloud-ts directory exists
148- await fs . mkdir ( 'cloud-ts' , { recursive : true } ) ;
149-
150- // Perform initial compilation
151- await compileAll ( ) ;
152-
153- // Watch for changes
154- watchForChanges ( ) ;
155-
156- console . log ( 'Cloud-TS watch process started. Press Ctrl+C to stop.' ) ;
157- console . log ( 'Edit, save, or delete TypeScript files in cloud-ts directory to automatically sync them.' ) ;
158- } catch ( err ) {
159- console . error ( `Watch process failed: ${ err . message } ` ) ;
160- process . exit ( 1 ) ;
161- }
87+ await fs . mkdir ( 'cloud-ts' , { recursive : true } ) ;
88+ await compileAll ( ) ;
89+ watchForChanges ( ) ;
90+ console . log ( 'Cloud-TS watch process started. Press Ctrl+C to stop.' ) ;
16291} ;
16392
164- main ( ) ;
93+ main ( ) . catch ( err => {
94+ console . error ( `Watch process failed: ${ err . message } ` ) ;
95+ process . exit ( 1 ) ;
96+ } ) ;
0 commit comments