ihimnm 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/LICENSE +1 -1
  2. package/index.js +47 -37
  3. package/package.json +1 -1
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Bjorn Lu
3
+ Copyright (c) 2026 Bjorn Lu
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // @ts-check
3
4
  import fs from 'node:fs'
4
5
  import path from 'node:path'
5
6
 
@@ -19,8 +20,7 @@ if (!isRecursive) {
19
20
  process.exit(1)
20
21
  }
21
22
 
22
- const found = crawlDependencies(packageJsonPath, [], true)
23
- if (!found) console.log(green('None found!'))
23
+ crawlDependencies(packageJsonPath, [], logDep, true)
24
24
  }
25
25
  // If recursive, use nested package.json from cwd
26
26
  else {
@@ -31,9 +31,16 @@ else {
31
31
  }
32
32
 
33
33
  for (const packageJsonPath of packageJsonPaths) {
34
- console.log(`${packageJsonPath}:`)
35
- const found = crawlDependencies(packageJsonPath, [], true)
36
- if (!found) console.log(green('None found!'))
34
+ let hasLogged = false
35
+ const _logDep = (/** @type {string[]} */ depPath) => {
36
+ if (!hasLogged) {
37
+ console.log(`${packageJsonPath}:`)
38
+ hasLogged = true
39
+ }
40
+ logDep(depPath)
41
+ }
42
+
43
+ crawlDependencies(packageJsonPath, [], _logDep, true, packageJsonPaths)
37
44
  }
38
45
  }
39
46
 
@@ -43,20 +50,24 @@ if (allFoundDeps.size) {
43
50
  const padNum = sortedDepNames.length.toString().length + 1
44
51
  for (let i = 0; i < sortedDepNames.length; i++) {
45
52
  const depName = sortedDepNames[i]
46
- const numStr = dim(`${i + 1}.`.padStart(padNum))
47
- console.log(`${numStr} ${red(depName)} ${dim(`(${allFoundDeps.get(depName)})`)}`)
53
+ const numStr = styleText('dim', `${i + 1}.`.padStart(padNum))
54
+ const depNum = allFoundDeps.get(depName) || 0
55
+ console.log(`${numStr} ${styleText('red', depName)} ${styleText('dim', `(${depNum})`)}`)
48
56
  }
57
+ } else {
58
+ console.log(styleText('green', 'None found!'))
49
59
  }
50
60
 
51
61
  /**
52
62
  * @param {string} pkgJsonPath
53
63
  * @param {string[]} parentDepNames
64
+ * @param {(depPath: string[]) => void} onMatch
54
65
  * @param {boolean} isRoot
66
+ * @param {string[]} skipPaths
55
67
  */
56
- function crawlDependencies(pkgJsonPath, parentDepNames, isRoot = false) {
57
- let found = false
68
+ function crawlDependencies(pkgJsonPath, parentDepNames, onMatch, isRoot = false, skipPaths = []) {
58
69
  const pkgJsonContent = fs.readFileSync(pkgJsonPath, 'utf8')
59
- const pkgJson = JSON.parse(pkgJsonContent)
70
+ const pkgJson = JSON.parse(pkgJsonContent.trim()) // trim to remove BOM if any
60
71
  const pkgDependencies = Object.keys(pkgJson.dependencies || {})
61
72
 
62
73
  if (isRoot) {
@@ -67,8 +78,7 @@ function crawlDependencies(pkgJsonPath, parentDepNames, isRoot = false) {
67
78
  // - from contributors list
68
79
  // - from @.../eslint-config dev dep
69
80
  else if (pkgJsonContent.includes(user)) {
70
- logDep(pkgJson.name, parentDepNames)
71
- found = true
81
+ onMatch(parentDepNames.concat(pkgJson.name))
72
82
  const foundCount = allFoundDeps.get(pkgJson.name) || 0
73
83
  allFoundDeps.set(pkgJson.name, foundCount + 1)
74
84
  }
@@ -79,16 +89,16 @@ function crawlDependencies(pkgJsonPath, parentDepNames, isRoot = false) {
79
89
 
80
90
  const depPkgJsonPath = findPkgJsonPath(depName, path.dirname(pkgJsonPath))
81
91
  if (!depPkgJsonPath) continue
92
+ if (skipPaths.includes(depPkgJsonPath)) continue
82
93
 
83
94
  const nestedFound = crawlDependencies(
84
95
  depPkgJsonPath,
85
- isRoot ? [] : parentDepNames.concat(pkgJson.name)
96
+ isRoot ? [] : parentDepNames.concat(pkgJson.name),
97
+ onMatch,
98
+ false,
99
+ skipPaths
86
100
  )
87
-
88
- found = found || nestedFound
89
101
  }
90
-
91
- return found
92
102
  }
93
103
 
94
104
  /**
@@ -158,30 +168,30 @@ function getUser() {
158
168
  }
159
169
 
160
170
  /**
161
- * @param {string} depName
162
- * @param {string[]} parentPackageNames
163
- */
164
- function logDep(depName, parentPackageNames) {
165
- console.log(dim(parentPackageNames.map((n) => n + ' > ').join('')) + red(depName))
166
- }
167
-
168
- /**
169
- * @param {string} str
170
- */
171
- function red(str) {
172
- return `\x1b[1m\x1b[31m${str}\x1b[0m`
173
- }
174
-
175
- /**
176
- * @param {string} str
171
+ * @param {string[]} depPath
177
172
  */
178
- function green(str) {
179
- return `\x1b[1m\x1b[32m${str}\x1b[0m`
173
+ function logDep(depPath) {
174
+ const parents = depPath.slice(0, -1)
175
+ const child = depPath[depPath.length - 1]
176
+ console.log(styleText('dim', parents.map((n) => n + ' > ').join('')) + styleText('red', child))
180
177
  }
181
178
 
182
179
  /**
180
+ * Import from `node:util` in the future when bumping required node version
181
+ * @param {string | string[]} color
183
182
  * @param {string} str
184
183
  */
185
- function dim(str) {
186
- return `\x1b[2m${str}\x1b[0m`
184
+ function styleText(color, str) {
185
+ /** @type {Record<string, string>} */
186
+ const colors = {
187
+ red: '\x1b[31m',
188
+ green: '\x1b[32m',
189
+ dim: '\x1b[2m',
190
+ bold: '\x1b[1m',
191
+ }
192
+ const reset = '\x1b[0m'
193
+ const prefix = Array.isArray(color)
194
+ ? color.map((c) => colors[c] || '').join('')
195
+ : colors[color] || ''
196
+ return `${prefix}${str}${reset}`
187
197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ihimnm",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "author": "Bjorn Lu",
6
6
  "license": "MIT",