Skip to content

Commit 979ec19

Browse files
committed
🎨 Make small iterative changes
1 parent 9552a96 commit 979ec19

6 files changed

Lines changed: 60 additions & 54 deletions

File tree

‎src/github/enterprise.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export default class Enterprise extends Base {
151151
this.#id = id
152152
this.#node_id = node_id
153153

154+
/* c8 ignore start */
154155
// Process each organization and fetch its repositories
155156
await Promise.all(
156157
nodes.map(async data => {
@@ -177,6 +178,7 @@ export default class Enterprise extends Base {
177178
})
178179
}),
179180
)
181+
/* c8 ignore stop */
180182

181183
// Sleep for 1s to avoid hitting the rate limit
182184
await wait(1000)

‎src/github/octokit.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ export default function getOctokit(token, hostname = null, debug = false) {
2424
throw new Error('GitHub token is required')
2525
}
2626

27-
const logger = log('octokit', token, debug)
27+
// Create separate logger instance for Octokit
28+
const logger = log('octokit', token, debug, true)
2829

2930
// Normalize hostname for GitHub Enterprise servers
3031
if (hostname) {

‎src/github/owner.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export default class Owner extends Base {
132132
* @param {string} type - The owner type (user or organization)
133133
*/
134134
set type(type) {
135-
this.#type = type
135+
this.#type = type.toLowerCase()
136136
}
137137

138138
/**
@@ -178,7 +178,7 @@ export default class Owner extends Base {
178178
this.name = name
179179
this.id = id
180180
this.node_id = node_id
181-
this.type = (type || '').toLowerCase()
181+
this.type = type || ''
182182
} catch (error) {
183183
if (error.status === 404) {
184184
this.logger.error(`User ${user} not found`)

‎src/github/repository.js‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,13 @@ export default class Repository extends Base {
332332
}
333333
} catch (error) {
334334
if (error.status === 404 || error.message.includes('Could not resolve to a Repository')) {
335-
this.#logger.error(`Repository ${repoName} not found.`)
336-
337-
return {}
335+
this.logger.error(`Repository ${repoName} not found.`)
338336
} else {
339-
this.#logger.error(`Failed to fetch repository ${repoName}: ${error.message}`)
340-
return {}
337+
this.logger.error(`Failed to fetch repository ${repoName}: ${error.message}`)
341338
}
339+
340+
// Rethrow the error to be handled by the caller
341+
throw error
342342
}
343343
}
344344

@@ -367,7 +367,7 @@ export default class Repository extends Base {
367367

368368
const wfs = []
369369
if (repository.object && repository.object.entries) {
370-
for (const entry of repository.object.entries) {
370+
for await (const entry of repository.object.entries) {
371371
// Skip non-YAML files
372372
if (!entry.path.endsWith('.yml') && !entry.path.endsWith('.yaml')) continue
373373

‎src/github/workflow.js‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ export default class Workflow extends Base {
256256
workflow_id: path,
257257
})
258258

259-
// wait 0.5s to avoid rate limit
260-
await wait(500)
259+
// wait 1s to avoid rate limit
260+
await wait(1000)
261261

262262
const {
263263
data: {workflow_runs: runs},
@@ -298,15 +298,21 @@ export default class Workflow extends Base {
298298
}
299299
}
300300

301-
getYaml() {
301+
/**
302+
* Parses the workflow text as YAML.
303+
* If the text is truncated, it logs a warning and returns null.
304+
* If the YAML is malformed, it logs an error and returns null.
305+
* @returns {Promise<object|null>} The parsed YAML object or null if parsing fails
306+
*/
307+
async getYaml() {
302308
if (this.#isTruncated) {
303309
this.logger.warn('Workflow text is truncated. Skipping YAML parsing.')
304310

305311
return null
306312
}
307313

308314
try {
309-
return load(this.#text, 'utf8')
315+
return await load(this.#text, 'utf8')
310316
} catch (error) {
311317
this.logger.error(`Malformed YAML: ${error.message}`)
312318

‎src/util/log.js‎

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,16 @@ export class Log {
2828
this.#spinner = this.#isDebug ? null : ora()
2929

3030
if (this.#isDebug) {
31-
this.#logger = this.#createWinstonLogger()
31+
this.#logger = this.createWinstonLogger()
3232
}
3333
}
3434

35-
/* c8 ignore start */
36-
3735
/**
3836
* Creates Winston logger configuration for debug mode.
3937
* @returns {winston.Logger} Configured Winston logger instance
4038
* @private
4139
*/
42-
#createWinstonLogger() {
40+
createWinstonLogger() {
4341
// Common format for timestamp and message formatting
4442
const commonFormat = winston.format.printf(({timestamp, level, message, ...meta}) => {
4543
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta, null, 2)}` : ''
@@ -72,7 +70,7 @@ export class Log {
7270
}),
7371
new winston.transports.File({
7472
level: 'debug',
75-
filename: `logs/debug.${this.#entity.replace('/', '_')}.log`,
73+
filename: `logs/debug.${this.#entity.replace('/', '_')}.${new Date().toISOString().slice(0, 10)}.log`,
7674
format: fileFormat,
7775
}),
7876
],
@@ -85,7 +83,7 @@ export class Log {
8583
* @returns {string} Formatted message string
8684
* @private
8785
*/
88-
#formatMessage(msg) {
86+
formatMessage(msg) {
8987
return typeof msg === 'object' && msg !== null ? JSON.stringify(msg) : msg
9088
}
9189

@@ -97,16 +95,14 @@ export class Log {
9795
* @param {string} [level='info'] - The log level (info, warn, error, debug)
9896
* @private
9997
*/
100-
#logInDebugMode(message, level = 'info') {
98+
logInDebugMode(message, level = 'info') {
10199
if (this.#logger) {
102100
this.#logger.log(level, message)
103101
} else {
104102
console.log(message)
105103
}
106104
}
107105

108-
/* c8 ignore stop */
109-
110106
get entity() {
111107
return this.#entity
112108
}
@@ -119,16 +115,14 @@ export class Log {
119115
return this.#isDebug
120116
}
121117

122-
/* c8 ignore start */
123-
124118
/**
125119
* Masks sensitive tokens in objects or strings.
126120
* Recursively looks for and replaces any occurrences of the authentication token
127121
* to prevent accidental exposure in logs.
128122
* @param {any} value - The value to mask (object or string)
129123
* @returns {any} The masked value with sensitive information replaced by '***'
130124
*/
131-
#maskSensitive(value) {
125+
maskSensitive(value) {
132126
// Early return if no token to mask or value is null/undefined
133127
if (!this.#token || value == null) {
134128
return value
@@ -137,7 +131,7 @@ export class Log {
137131
// Handle string values directly
138132
if (typeof value === 'string') {
139133
// Using a safe string replacement with global flag to replace all occurrences
140-
return this.#token ? value.replace(new RegExp(this.#escapeRegExp(this.#token), 'g'), '***') : value
134+
return this.#token ? value.replace(new RegExp(this.escapeRegExp(this.#token), 'g'), '***') : value
141135
}
142136

143137
// Handle objects (including arrays)
@@ -154,11 +148,11 @@ export class Log {
154148

155149
// Handle string values that contain the token
156150
if (typeof clone[key] === 'string' && this.#token && clone[key].includes(this.#token)) {
157-
clone[key] = clone[key].replace(new RegExp(this.#escapeRegExp(this.#token), 'g'), '***')
151+
clone[key] = clone[key].replace(new RegExp(this.escapeRegExp(this.#token), 'g'), '***')
158152
}
159153
// Recursively process nested objects
160154
else if (typeof clone[key] === 'object' && clone[key] !== null) {
161-
clone[key] = this.#maskSensitive(clone[key])
155+
clone[key] = this.maskSensitive(clone[key])
162156
}
163157
}
164158

@@ -174,7 +168,7 @@ export class Log {
174168
* @returns {string} The escaped string
175169
* @private
176170
*/
177-
#escapeRegExp(string) {
171+
escapeRegExp(string) {
178172
// Escape special RegExp characters to avoid regex syntax errors
179173
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
180174
}
@@ -186,15 +180,15 @@ export class Log {
186180
* @param {...any} args - Additional arguments to log
187181
* @private
188182
*/
189-
#logWithPrefix(consoleMethod, msg, ...args) {
183+
logWithPrefix(consoleMethod, msg, ...args) {
190184
// Mask sensitive data once for both message and arguments
191-
const maskedMsg = this.#maskSensitive(msg)
192-
const maskedArgs = this.#maskSensitive(...args)
185+
const maskedMsg = this.maskSensitive(msg)
186+
const maskedArgs = this.maskSensitive(...args)
193187

194188
if (this.#isDebug && this.#logger) {
195189
// Use Winston for debug mode logging
196-
const level = this.#getWinstonLevel(consoleMethod)
197-
const message = this.#formatMessage(maskedMsg)
190+
const level = this.getWinstonLevel(consoleMethod)
191+
const message = this.formatMessage(maskedMsg)
198192

199193
if (args.length > 0) {
200194
this.#logger.log(level, message, maskedArgs)
@@ -217,7 +211,7 @@ export class Log {
217211
* @returns {string} The corresponding Winston log level
218212
* @private
219213
*/
220-
#getWinstonLevel(consoleMethod) {
214+
getWinstonLevel(consoleMethod) {
221215
// Map console methods to Winston log levels for proper log categorization
222216
switch (consoleMethod) {
223217
case console.error:
@@ -232,15 +226,13 @@ export class Log {
232226
}
233227
}
234228

235-
/* c8 ignore stop */
236-
237229
/**
238230
* Logs a message without any prefix.
239231
* @param {string|object} msg - The message to log
240232
* @param {...any} args - Additional arguments to log
241233
*/
242234
log(msg, ...args) {
243-
this.#logWithPrefix(console.log, msg, ...args)
235+
this.logWithPrefix(console.log, msg, ...args)
244236
}
245237

246238
/**
@@ -249,7 +241,7 @@ export class Log {
249241
* @param {...any} args - Additional arguments to log
250242
*/
251243
info(msg, ...args) {
252-
this.#logWithPrefix(console.log, msg, ...args)
244+
this.logWithPrefix(console.log, msg, ...args)
253245
}
254246

255247
/**
@@ -260,7 +252,7 @@ export class Log {
260252
warn(msg, ...args) {
261253
// Skip warning logging when not in debug mode for better performance
262254
if (!this.#isDebug) return
263-
this.#logWithPrefix(console.warn, msg, ...args)
255+
this.logWithPrefix(console.warn, msg, ...args)
264256
}
265257

266258
/**
@@ -269,7 +261,7 @@ export class Log {
269261
* @param {...any} args - Additional arguments to log
270262
*/
271263
error(msg, ...args) {
272-
this.#logWithPrefix(console.error, msg, ...args)
264+
this.logWithPrefix(console.error, msg, ...args)
273265
}
274266

275267
/**
@@ -281,7 +273,7 @@ export class Log {
281273
debug(msg, ...args) {
282274
// Skip debug logging when not in debug mode for better performance
283275
if (!this.#isDebug) return
284-
this.#logWithPrefix(console.debug, msg, ...args)
276+
this.logWithPrefix(console.debug, msg, ...args)
285277
}
286278

287279
/**
@@ -290,9 +282,9 @@ export class Log {
290282
* @param {string} text - The text to display
291283
*/
292284
start(text) {
293-
const maskedText = this.#maskSensitive(text)
285+
const maskedText = this.maskSensitive(text)
294286
if (this.#isDebug) {
295-
this.#logInDebugMode(maskedText)
287+
this.logInDebugMode(maskedText)
296288
} else if (this.#spinner) {
297289
this.#spinner.start(maskedText)
298290
}
@@ -307,15 +299,15 @@ export class Log {
307299
* @param {string} [options.prefixText=''] - Optional prefix text to prepend
308300
* @param {string} [options.suffixText=''] - Optional suffix text to append
309301
*/
310-
stopAndPersist({symbol, text, prefixText = '', suffixText = ''}) {
302+
async stopAndPersist({symbol, text, prefixText = '', suffixText = ''}) {
311303
// Mask all text components
312-
const maskedText = this.#maskSensitive(text)
313-
const maskedPrefixText = this.#maskSensitive(prefixText)
314-
const maskedSuffixText = this.#maskSensitive(suffixText)
304+
const maskedText = this.maskSensitive(text)
305+
const maskedPrefixText = this.maskSensitive(prefixText)
306+
const maskedSuffixText = this.maskSensitive(suffixText)
315307

316308
if (this.#isDebug) {
317309
const message = [maskedPrefixText, symbol, maskedText, maskedSuffixText].join(' ')
318-
this.#logInDebugMode(message)
310+
this.logInDebugMode(message)
319311
} else if (this.#spinner) {
320312
this.#spinner.stopAndPersist({
321313
symbol,
@@ -333,9 +325,9 @@ export class Log {
333325
* @param {string} text - The failure message
334326
*/
335327
fail(text) {
336-
const maskedText = this.#maskSensitive(text)
328+
const maskedText = this.maskSensitive(text)
337329
if (this.#isDebug) {
338-
this.#logInDebugMode(maskedText, 'error')
330+
this.logInDebugMode(maskedText, 'error')
339331
} else if (this.#spinner) {
340332
this.#spinner.fail(maskedText)
341333
}
@@ -347,9 +339,9 @@ export class Log {
347339
* @param {string} newText - The new text to display
348340
*/
349341
set text(newText) {
350-
const maskedText = this.#maskSensitive(newText)
342+
const maskedText = this.maskSensitive(newText)
351343
if (this.#isDebug) {
352-
this.#logInDebugMode(maskedText)
344+
this.logInDebugMode(maskedText)
353345
} else if (this.#spinner) {
354346
this.#spinner.text = maskedText
355347
}
@@ -372,9 +364,14 @@ let instance = null
372364
* @param {string} entity - The entity name used for log file naming
373365
* @param {string} token - The authentication token to mask in logs
374366
* @param {boolean} [isDebug=false] - Enable debug mode
367+
* @param {boolean} [createNewInstance=false] - Create a new instance if true, otherwise return existing instance
375368
* @returns {Log} Instance of Log class
376369
*/
377-
export default function log(entity, token, isDebug = false) {
370+
export default function log(entity, token, isDebug = false, createNewInstance = false) {
371+
if (createNewInstance === true) {
372+
return new Log(entity, token, isDebug)
373+
}
374+
378375
if (!instance) {
379376
instance = new Log(entity, token, isDebug)
380377
}

0 commit comments

Comments
 (0)