privacy-brush 1.0.0 → 1.0.2

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.
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "privacy-brush",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Automatically mask sensitive information in terminal outputs and logs. Keep your data safe when sharing.",
5
5
  "main": "src/index.mjs",
6
6
  "module": "src/index.mjs",
7
7
  "bin": "src/cli.mjs",
8
8
  "scripts": {
9
- "test": "node --test",
9
+ "test": "node --test || nvm use 22 && sleep 0.5 && node --test",
10
10
  "typecheck": "tsgo --noEmit",
11
11
  "check": "npm run typecheck && npm run test",
12
12
  "========== Publishing ==========": "",
@@ -17,10 +17,31 @@
17
17
  "postversion": "npm publish && git push origin HEAD && git push --tags",
18
18
  "publishd": "npm publish --dry-run"
19
19
  },
20
- "keywords": [],
21
- "author": "",
22
- "license": "ISC",
20
+ "keywords": [
21
+ "privacy",
22
+ "mask",
23
+ "masking",
24
+ "sensitive",
25
+ "guard",
26
+ "shield",
27
+ "safe",
28
+ "sharing",
29
+ "sanitize",
30
+ "obfuscate",
31
+ "blur",
32
+ "logs",
33
+ "terminal",
34
+ "security"
35
+ ],
36
+ "author": "legend80s",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/legend80s/privacy-brush.git"
41
+ },
42
+ "homepage": "https://github.com/legend80s/privacy-brush",
23
43
  "devDependencies": {
44
+ "@typescript/native-preview": "7.0.0-dev.20260122.2",
24
45
  "@types/node": "^25.0.10"
25
46
  }
26
47
  }
package/src/cli.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env node
2
+
1
3
  import { PrivacyBrush } from "./index.mjs"
2
4
  import { parsedResult, verbose } from "./lib/parse-args.mjs"
3
5
 
@@ -26,6 +28,7 @@ async function main() {
26
28
  }
27
29
 
28
30
  const { values } = result
31
+ verbose && console.log("values:", values)
29
32
 
30
33
  if (values.help) {
31
34
  await printHelp()
@@ -37,9 +40,6 @@ async function main() {
37
40
  return
38
41
  }
39
42
 
40
- verbose && console.log("values:", values)
41
- // console.log("positionals:", positionals)
42
-
43
43
  const config = values
44
44
 
45
45
  const masker = new PrivacyBrush({
@@ -48,6 +48,23 @@ async function main() {
48
48
  customPatterns: config.pattern,
49
49
  })
50
50
 
51
+ if (values["list-patterns"]) {
52
+ // instantiate PrivacyBrush to access default patterns
53
+ const patterns = masker.defaultSensitivePatterns
54
+
55
+ console.log("\nBuilt-in patterns:")
56
+ console.table(patterns.map(({ replacer: _, ...args }) => args))
57
+
58
+ if (masker.customSensitivePatterns.length) {
59
+ console.log("Custom patterns:")
60
+ console.table(
61
+ masker.customSensitivePatterns.map(({ replacer: _, ...args }) => args),
62
+ )
63
+ }
64
+
65
+ return
66
+ }
67
+
51
68
  // If an input file is provided, process it. If --output-file is provided write there, otherwise print to stdout.
52
69
  if (config["input-file"]) {
53
70
  try {
@@ -113,10 +130,13 @@ pnpx privacy-brush [options]
113
130
 
114
131
 
115
132
  ## Options:
116
- --input-file, -i Path to input file to mask and print to stdout
117
- --output-file, -o Path to write masked output (if given, write to this file)
133
+ --input-file, -i Path to input file to mask and print to stdout
134
+ --output-file, -o Path to write masked output (if given, write to this file)
118
135
  --mask, -m Character to use for masking (default: "█")
119
136
  --preserve-first, -p Whether to preserve the first part of version numbers (default: true, \`--no-preserve-first\` to false)
137
+ --pattern, -r Custom regex pattern(s) to mask (can be used multiple times. E.g. --pattern '\\d{2,}' --pattern 'sk-([0-9a-z]{20,})')
138
+ --list-patterns List all built-in patterns
139
+
120
140
  --help, -h Show this help message (default: false)
121
141
  --verbose Enable verbose output (default: false)
122
142
  --version, -v Show version information (default: false)
package/src/cli.test.mjs CHANGED
@@ -27,12 +27,13 @@ test("❯ echo | node src/cli.mjs", async () => {
27
27
  test("--mask", async () => {
28
28
  const actual = execSync(
29
29
  'echo Microsoft Windows [Version 10.0.12345.6785] | node src/cli.mjs --mask "🔒" --no-preserve-first',
30
- ).toString("utf8")
30
+ )
31
+ .toString("utf8")
32
+ .trim()
31
33
 
32
34
  // console.log(`actual:|${actual}|`)
33
35
 
34
- const expected =
35
- "Microsoft Windows [Version 🔒🔒.🔒.🔒🔒🔒🔒🔒.🔒🔒🔒🔒] \r\n"
36
+ const expected = "Microsoft Windows [Version 🔒🔒.🔒.🔒🔒🔒🔒🔒.🔒🔒🔒🔒]"
36
37
  assert.strictEqual(actual, expected)
37
38
  })
38
39
 
@@ -78,33 +79,41 @@ DEBUG: OS: Windows 10.0.12345
78
79
  test(`custom patterns`, () => {
79
80
  const input = `DEEPSEEK_API_KEY=sk-af75149812524eb08eb302bf9604c8e8`
80
81
 
81
- const actual = execSync(
82
- `echo ${input} | node src/cli.mjs --pattern /sk-([a-z0-9]{20,})/`,
83
- ).toString("utf8")
82
+ const actual = spawnSync(
83
+ "node",
84
+ ["src/cli.mjs", "--pattern", "/sk-([a-z0-9]{20,})/"],
85
+ { input },
86
+ ).stdout.toString("utf8")
84
87
 
85
- const expected = "DEEPSEEK_API_KEY=sk-████████████████████████████████ \r\n"
88
+ const expected = "DEEPSEEK_API_KEY=sk-████████████████████████████████"
86
89
  assert.strictEqual(actual, expected)
87
90
  })
88
91
 
89
- test(`custom patterns`, () => {
92
+ test(`custom patterns without ()`, () => {
90
93
  const input = `DEEPSEEK_API_KEY=sk-af75149812524eb08eb302bf9604c8e8`
91
94
 
92
- const actual = execSync(
93
- `echo ${input} | node src/cli.mjs --pattern /sk-[a-z0-9]{20,}/`,
94
- ).toString("utf8")
95
+ const actual = spawnSync(
96
+ "node",
97
+ ["src/cli.mjs", "--pattern", "/sk-[a-z0-9]{20,}/"],
98
+ { input },
99
+ )
100
+ .stdout.toString("utf8")
101
+ .trim()
95
102
 
96
- const expected = "DEEPSEEK_API_KEY=███████████████████████████████████ \r\n"
103
+ const expected = "DEEPSEEK_API_KEY=███████████████████████████████████"
97
104
  assert.strictEqual(actual, expected)
98
105
  })
99
106
 
100
107
  test(`custom patterns`, () => {
101
108
  const input = `DEEPSEEK_API_KEY=sk-af75149812524eb08eb302bf9604c8e8`
102
109
 
103
- const actual = execSync(
104
- `echo ${input} | node src/cli.mjs --pattern /([0-9]{2,})/`,
105
- ).toString("utf8")
110
+ const actual = spawnSync(
111
+ "node",
112
+ ["src/cli.mjs", "--pattern", "/([0-9]{2,})/"],
113
+ { input },
114
+ ).stdout.toString("utf8")
106
115
 
107
- const expected = "DEEPSEEK_API_KEY=sk-af███████████eb██eb███bf████c8e8 \r\n"
116
+ const expected = "DEEPSEEK_API_KEY=sk-af███████████eb██eb███bf████c8e8"
108
117
  assert.strictEqual(actual, expected)
109
118
  })
110
119
 
package/src/index.mjs CHANGED
@@ -68,6 +68,22 @@ export class PrivacyBrush {
68
68
  return this.maskVersion(match)
69
69
  },
70
70
  },
71
+
72
+ // user name `/Users/test/code/` => `/Users/████/code/`
73
+ {
74
+ /** @type {IPatternName} */
75
+ name: "user_name_in_path",
76
+ regex: /\/Users\/([^\/]+)\//g,
77
+ /**
78
+ * Handle user name in file path masking.
79
+ * @param {string} match
80
+ * @param {string} userName
81
+ * @returns {string}
82
+ */
83
+ replacer: (match, userName) => {
84
+ return match.replace(userName, this.maskChar.repeat(userName.length))
85
+ },
86
+ },
71
87
  ]
72
88
 
73
89
  return allPatterns
@@ -187,6 +203,7 @@ export class PrivacyBrush {
187
203
  let result = text
188
204
 
189
205
  this.sensitivePatterns.forEach(pattern => {
206
+ verbose && console.log("pattern:", pattern)
190
207
  result = result.replace(pattern.regex, pattern.replacer)
191
208
  })
192
209
 
@@ -4,6 +4,11 @@
4
4
  export const defaultConfig = {
5
5
  maskChar: "█",
6
6
  preserveFirstPart: true, // 是否保留版本号的第一部分
7
- maskPatternNames: ["windows_version", "browser_version", "ip_address"],
7
+ maskPatternNames: [
8
+ "windows_version",
9
+ "browser_version",
10
+ "ip_address",
11
+ "user_name_in_path",
12
+ ],
8
13
  customPatterns: [],
9
14
  }
@@ -55,6 +55,10 @@ export const parsedResult = safeCall(() =>
55
55
  type: "boolean",
56
56
  short: "v",
57
57
  },
58
+ // list built-in patterns
59
+ "list-patterns": {
60
+ type: "boolean",
61
+ },
58
62
  },
59
63
  }),
60
64
  )