Skip to content

Commit 9b32330

Browse files
committed
fix: improve path handling and fix event listener leak
Ref: #228 (comment) - Replace `process.cwd()` with `__dirname` for reliable path resolution - Fix HTTP server connection listener leak on multiple start/stop cycles - Add default empty string for ref parameter in internalLinkBuilder - Replace `parseInt()` with `Number()` for better type conversion - Add `implementation_status` enum to `indexData` schema
1 parent 867bd7d commit 9b32330

File tree

7 files changed

+28
-24
lines changed

7 files changed

+28
-24
lines changed

scripts/export-checklists.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const { join } = require('path');
4141
const result = await knex.raw(query)
4242

4343
// Write the result to a JSON file
44-
const outputPath = join(process.cwd(), 'output', 'checklists.json')
44+
const outputPath = join(__dirname, '../output', 'checklists.json')
4545
writeFileSync(outputPath, JSON.stringify(result.rows, null, 2))
4646

4747
console.log(`Data exported to ${outputPath}`)

scripts/export-checks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const { join } = require('path')
3434
return { ...check, resources }
3535
})
3636

37-
writeFileSync(join(process.cwd(), 'output', 'checks.json'), JSON.stringify(formattedChecks, null, 2))
37+
writeFileSync(join(__dirname, '../output', 'checks.json'), JSON.stringify(formattedChecks, null, 2))
3838
console.log('Checks exported to checks.json')
3939
await knex.destroy()
4040
})()

src/httpServer/index.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ const server = http.createServer(app)
4747
// Track all active connections
4848
const connections = new Set()
4949

50+
// Set up connection tracking once (prevents listener leaks on multiple start/stop cycles)
51+
server.on('connection', connection => {
52+
connections.add(connection)
53+
connection.on('close', () => connections.delete(connection))
54+
})
55+
5056
module.exports = () => ({
5157
start: async () => {
5258
const isDbConnected = await checkDatabaseConnection(knex)
@@ -64,13 +70,6 @@ module.exports = () => ({
6470
})
6571
})
6672

67-
// Track connections
68-
server.on('connection', connection => {
69-
connections.add(connection)
70-
connection.on('close', () => {
71-
connections.delete(connection)
72-
})
73-
})
7473
return server
7574
},
7675
stop: async () => {

src/httpServer/routers/website.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function createWebRouter (knex, express) {
2121
})
2222

2323
router.get('/projects/:id', async (req, res) => {
24-
const projectId = parseInt(req.params.id)
24+
const projectId = Number(req.params.id)
2525
if (isNaN(projectId)) {
2626
logger.error(`Invalid project ID: ${req.params.id}`)
2727
return res.status(404).render(notFoundTemplate)

src/reports/index.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ const { join } = require('path')
55
const { initializeStore } = require('../store')
66
const { validateProjectData, validateIndexData } = require('../schemas')
77

8-
const indexTemplatePath = join(process.cwd(), 'src', 'reports', 'templates', 'index.ejs')
9-
const projectTemplatePath = join(process.cwd(), 'src', 'reports', 'templates', 'project.ejs')
10-
const assetsFolder = join(process.cwd(), 'src', 'reports', 'assets')
11-
const destinationFolder = join(process.cwd(), 'output')
8+
const baseTemplatesPath = join(__dirname, 'templates')
9+
const indexTemplatePath = join(baseTemplatesPath, 'index.ejs')
10+
const projectTemplatePath = join(baseTemplatesPath, 'project.ejs')
11+
const assetsFolder = join(__dirname, 'assets')
12+
const destinationFolder = join(__dirname, '../../output')
1213
const copyFolder = async (from, to) => {
1314
try {
1415
// Ensure the target directory exists
@@ -108,7 +109,7 @@ const collectProjectData = async (knex, projectId) => {
108109
}
109110
}
110111

111-
const internalLinkBuilder = (mode = 'static') => (ref, project) => {
112+
const internalLinkBuilder = (mode = 'static') => (ref = '', project) => {
112113
let finalRef = ref
113114
// remove leading slash
114115
if (mode === 'static') {
@@ -197,7 +198,7 @@ const generateStaticReports = async (knex, options = { clearPreviousReports: fal
197198
// Populate the project HTML template
198199
const projectHtml = ejs.render(projectTemplate, projectsData[project.name], {
199200
filename: projectTemplatePath,
200-
views: [join(process.cwd(), 'src', 'reports', 'templates')]
201+
views: [join(__dirname, 'templates')]
201202
})
202203
// @TODO: Prevent overwriting (edge case) at creation level
203204
if (project.name !== 'index') {
@@ -208,8 +209,8 @@ const generateStaticReports = async (knex, options = { clearPreviousReports: fal
208209
}
209210

210211
await Promise.all([
211-
writeFile('output/index_data.json', JSON.stringify(indexData, null, 2)),
212-
writeFile('output/projects_data.json', JSON.stringify(projectsData, null, 2))
212+
writeFile(join(destinationFolder, 'index_data.json'), JSON.stringify(indexData, null, 2)),
213+
writeFile(join(destinationFolder, 'projects_data.json'), JSON.stringify(projectsData, null, 2))
213214
])
214215

215216
// copy assets folder
@@ -218,11 +219,11 @@ const generateStaticReports = async (knex, options = { clearPreviousReports: fal
218219
// Populate the index HTML template
219220
const indexHtml = ejs.render(indexTemplate, indexData, {
220221
filename: indexTemplatePath,
221-
views: [join(process.cwd(), 'src', 'reports', 'templates')]
222+
views: [join(__dirname, 'templates')]
222223
})
223224

224225
// Save the index HTML file
225-
await writeFile('output/index.html', indexHtml)
226+
await writeFile(join(destinationFolder, 'index.html'), indexHtml)
226227
logger.info('Reports generated successfully')
227228
}
228229

src/schemas/indexData.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
"id": { "type": "integer" },
4444
"checklist_id": { "type": "integer" },
4545
"description": { "type": "string" },
46+
"implementation_status": {
47+
"type": "string",
48+
"enum": ["pending", "in_progress", "completed"]
49+
},
4650
"created_at": { "type": ["string", "object"], "format": "date-time" },
4751
"updated_at": { "type": ["string", "object"], "format": "date-time" }
4852
}

src/utils/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const ensureGithubToken = () => {
5555

5656
const getSeverityFromPriorityGroup = (priorityGroup) => {
5757
const priorityType = priorityGroup[0]
58-
const priorityValue = parseInt(priorityGroup.slice(1), 10)
58+
const priorityValue = Number(priorityGroup.slice(1), 10)
5959
// Recommendations (Rxx)
6060
if (priorityType === 'R') {
6161
return 'info'
@@ -107,13 +107,13 @@ const isDateWithinPolicy = (targetDate, policy) => {
107107

108108
// Handle expiration policy
109109
if (policy.endsWith('d')) {
110-
const days = parseInt(policy.replace('d', ''), 10)
110+
const days = Number(policy.replace('d', ''), 10)
111111
expirationDate = add(targetDateObj, { days })
112112
} else if (policy.endsWith('m')) {
113-
const months = parseInt(policy.replace('m', ''), 10)
113+
const months = Number(policy.replace('m', ''), 10)
114114
expirationDate = add(targetDateObj, { months })
115115
} else if (policy.endsWith('q')) {
116-
const quarters = parseInt(policy.replace('q', ''), 10)
116+
const quarters = Number(policy.replace('q', ''), 10)
117117
expirationDate = add(targetDateObj, { months: quarters * 3 })
118118
} else {
119119
throw new Error('Unsupported policy format')

0 commit comments

Comments
 (0)