1
+ import express from 'express' ;
2
+ import multer from 'multer' ;
3
+ import { fileURLToPath } from 'url' ;
4
+ import { dirname , join , extname } from 'path' ;
5
+ import { promises as fs } from 'fs' ;
6
+ import cors from 'cors' ;
7
+
8
+ import { parseSDF } from './src/sdfProcess.js' ;
9
+ import { parseVerilog } from './src/vProcess.js' ;
10
+ import { mergeJsonForD3 } from './src/mergeVerilogSdf.js' ;
11
+
12
+ export const app = express ( ) ;
13
+ const PORT = 3001 ;
14
+
15
+ // Get absolute path
16
+ const __filename = fileURLToPath ( import . meta. url ) ;
17
+ const __dirname = dirname ( __filename ) ;
18
+
19
+ // Authorize CORS
20
+ app . use ( cors ( ) ) ;
21
+ app . use ( express . json ( ) ) ;
22
+
23
+ // Configure multer for handling SDF file upload
24
+ // Store file in memory, not on disk
25
+ const storage = multer . memoryStorage ( ) ;
26
+
27
+ // Filter to verify file type
28
+ const upload = multer ( {
29
+ storage : storage ,
30
+ fileFilter : ( req , file , cb ) => {
31
+ const fieldExtensionMap = {
32
+ sdfFile : [ '.sdf' ] ,
33
+ verilogFile : [ '.v' ]
34
+ } ;
35
+
36
+ // Check if the file field name is in the map
37
+ const fileExtension = extname ( file . originalname ) . toLowerCase ( ) ;
38
+ const allowedExtensions = fieldExtensionMap [ file . fieldname ] ;
39
+
40
+ if ( allowedExtensions && allowedExtensions . includes ( fileExtension ) ) {
41
+ cb ( null , true ) ;
42
+ } else {
43
+ req . fileValidationError = `Invalid file(s) format.` ;
44
+ cb ( null , false ) ;
45
+ }
46
+ } ,
47
+ } ) ;
48
+
49
+
50
+ // Endpoint for uploading and parsing SDF & Verilog file
51
+ app . post ( '/api/upload' , upload . fields ( [ { name : 'sdfFile' } , { name : 'verilogFile' } ] ) , async ( req , res ) => {
52
+ try {
53
+ // verify if files are uploaded
54
+ if ( req . fileValidationError ) {
55
+ return res . status ( 400 ) . send ( req . fileValidationError ) ;
56
+ }
57
+
58
+ const sdfFile = req . files ?. [ 'sdfFile' ] ?. [ 0 ] ;
59
+ const verilogFile = req . files ?. [ 'verilogFile' ] ?. [ 0 ] ;
60
+
61
+ // Check if files are uploaded
62
+ if ( ! sdfFile || ! verilogFile ) {
63
+ return res . status ( 400 ) . send ( 'Both SDF and Verilog files must be uploaded.' ) ;
64
+ }
65
+
66
+ const sdfContent = sdfFile . buffer . toString ( 'utf-8' ) . trim ( ) ;
67
+ const verilogContent = verilogFile . buffer . toString ( 'utf-8' ) . trim ( ) ;
68
+
69
+ if ( ! sdfContent || ! verilogContent ) {
70
+ return res . status ( 400 ) . send ( 'One or both uploaded files are empty.' ) ;
71
+ }
72
+
73
+ // Parse SDF and Verilog files
74
+ let sdfData , verilogData , commonInstances ;
75
+ try {
76
+ sdfData = parseSDF ( sdfContent ) ;
77
+ } catch ( error ) {
78
+ return res . status ( 500 ) . send ( 'Error parsing SDF file.' ) ;
79
+ }
80
+
81
+ try {
82
+ verilogData = parseVerilog ( verilogContent ) ;
83
+ } catch ( error ) {
84
+ return res . status ( 500 ) . send ( 'Error parsing Verilog file.' ) ;
85
+ }
86
+
87
+ try {
88
+ commonInstances = mergeJsonForD3 ( verilogData , sdfData ) ;
89
+ } catch ( error ) {
90
+ return res . status ( 500 ) . send ( 'Error merging files.' ) ;
91
+ }
92
+
93
+ // Save parsed SDF and Verilog files
94
+ try {
95
+ const projectName = req . body . projectName ;
96
+ if ( ! projectName ) {
97
+ return res . status ( 400 ) . send ( 'Project name is required.' ) ;
98
+ }
99
+
100
+ //try if folder 'parsed_files' exists
101
+ try {
102
+ await fs . access ( join ( __dirname , 'parsed_files' ) ) ;
103
+ } catch ( error ) {
104
+ try {
105
+ await fs . mkdir ( join ( __dirname , 'parsed_files' ) ) ;
106
+ } catch ( error ) {
107
+ return res . status ( 500 ) . send ( 'Error creating directory.' ) ;
108
+ }
109
+ }
110
+
111
+ const projectJSON_Path = join ( __dirname , 'parsed_files' , `${ projectName } .json` ) ;
112
+
113
+ //check if files exists
114
+ try {
115
+ // check if file exists
116
+ await fs . access ( projectJSON_Path ) ;
117
+ return res . status ( 400 ) . send ( 'The project already exists.' ) ;
118
+
119
+ } catch ( error ) {
120
+ try {
121
+ await fs . writeFile ( join ( projectJSON_Path ) , JSON . stringify ( commonInstances , null , 2 ) ) ;
122
+ res . status ( 200 ) . send ( 'Files uploaded successfully.' ) ;
123
+
124
+ } catch ( error ) {
125
+ res . status ( 500 ) . send ( 'Error saving parsed JSON files.' ) ;
126
+ }
127
+ }
128
+
129
+ } catch ( error ) {
130
+ res . status ( 500 ) . send ( 'Error saving parsed JSON files.' ) ;
131
+ }
132
+
133
+ } catch ( error ) {
134
+ res . status ( 500 ) . send ( 'Unexpected server error.' ) ;
135
+ }
136
+ } ) ;
137
+
138
+ // Endpoint to show a error message if no project name is provided
139
+ app . get ( '/api/map' , ( req , res ) => {
140
+ return res . status ( 400 ) . send ( 'Project name is required.' ) ;
141
+ } ) ;
142
+
143
+ // Endpoint API for sending parsed SDF file
144
+ app . get ( '/api/map/:projectName' , async ( req , res ) => {
145
+ try {
146
+ const projectName = req . params . projectName ;
147
+ if ( ! projectName ) {
148
+ return res . status ( 400 ) . send ( 'Project name is required.' ) ;
149
+ }
150
+
151
+ // Construct the file path using string concatenation
152
+ const jsonFilePath = join ( __dirname , 'parsed_files' , `${ projectName } .json` ) ;
153
+
154
+ // Check if the file exists
155
+ await fs . access ( jsonFilePath ) ;
156
+
157
+ // Read the file content
158
+ const jsonData = await fs . readFile ( jsonFilePath , 'utf-8' ) ;
159
+ res . json ( JSON . parse ( jsonData ) ) ;
160
+
161
+ } catch ( error ) {
162
+ if ( error . code === 'ENOENT' ) {
163
+ // File does not exist
164
+ return res . status ( 400 ) . send ( 'Project not found.' ) ;
165
+ }
166
+ res . status ( 500 ) . send ( 'Error reading parsed SDF JSON file.' ) ;
167
+ }
168
+ } ) ;
169
+
170
+ // Endpoint to delete a parsed SDF JSON file
171
+ app . delete ( '/api/delete-project/:projectName' , async ( req , res ) => {
172
+ try {
173
+ const projectName = req . params . projectName ;
174
+
175
+ // Validate projectName
176
+ if ( ! projectName || typeof projectName !== 'string' ) {
177
+ return res . status ( 400 ) . send ( 'Invalid project name.' ) ;
178
+ }
179
+
180
+ const projectPath = join ( __dirname , 'parsed_files' , `${ projectName } .json` ) ;
181
+
182
+ try {
183
+ // verify if file exists
184
+ await fs . access ( projectPath ) ;
185
+ } catch ( err ) {
186
+ // file does not exist
187
+ return res . status ( 404 ) . send ( 'Project does not exist.' ) ;
188
+ }
189
+
190
+ // Delete file
191
+ await fs . unlink ( projectPath ) ;
192
+ res . send ( 'File deleted successfully.' ) ;
193
+
194
+ } catch ( error ) {
195
+ res . status ( 500 ) . send ( 'Error deleting file, please try again later.' ) ;
196
+ }
197
+ } ) ;
198
+
199
+
200
+ // Endpoint to list all SDF files
201
+ app . get ( '/api/list' , async ( req , res ) => {
202
+ try {
203
+ const directoryPath = join ( __dirname , 'parsed_files' ) ;
204
+
205
+ // Check if the directory exists
206
+ try {
207
+ await fs . access ( directoryPath ) ;
208
+ } catch ( error ) {
209
+ // Create the directory if it doesn't exist
210
+ await fs . mkdir ( directoryPath , { recursive : true } ) ;
211
+ }
212
+
213
+ const entries = await fs . readdir ( directoryPath , { withFileTypes : true } ) ;
214
+
215
+ // Prepare an array to hold file information
216
+ const filesInfo = [ ] ;
217
+
218
+ // Iterate over entries to get file names and creation dates
219
+ for ( const entry of entries ) {
220
+ if ( entry . isFile ( ) && entry . name . endsWith ( '.json' ) ) {
221
+ const filePath = join ( directoryPath , entry . name ) ;
222
+ const stats = await fs . stat ( filePath ) ;
223
+
224
+ // Format the date to only include the date part (YYYY-MM-DD)
225
+ const createdDate = stats . birthtime . toISOString ( ) . split ( 'T' ) [ 0 ] ;
226
+
227
+ filesInfo . push ( {
228
+ name : entry . name . replace ( '.json' , '' ) ,
229
+ createdDate
230
+ } ) ;
231
+ }
232
+ }
233
+
234
+ res . json ( filesInfo ) ;
235
+ } catch ( error ) {
236
+ res . status ( 500 ) . send ( 'Error listing files.' ) ;
237
+ }
238
+ } ) ;
239
+
240
+ export const server = app . listen ( PORT , ( ) => { } ) ;
0 commit comments