pino-debugging 1.0.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.
- package/.borp.yaml +9 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +55 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +46 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +69 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/jsLinters/eslint.xml +6 -0
- package/.snyk +43 -0
- package/CHANGELOG.md +207 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +185 -0
- package/LICENSE +21 -0
- package/PUBLISH_GUIDE.md +352 -0
- package/README.md +241 -0
- package/SECURITY.md +67 -0
- package/SECURITY_IMPROVEMENTS.md +140 -0
- package/SECURITY_STATUS.md +56 -0
- package/benchmarks/basic.bench.js +62 -0
- package/benchmarks/deep-object.bench.js +68 -0
- package/benchmarks/object.bench.js +61 -0
- package/benchmarks/runbench.js +103 -0
- package/benchmarks/usage.txt +12 -0
- package/debug.js +55 -0
- package/docs/SECURITY_BEST_PRACTICES.md +364 -0
- package/eslint.config.js +3 -0
- package/index.js +118 -0
- package/package.json +83 -0
- package/scripts/security-check.js +171 -0
- package/test/index.js +100 -0
- package/test.js +42 -0
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pino-debugging",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "High performance debug logging",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "npm run deps && npm run lint && npm run test:unit",
|
|
8
|
+
"deps": "knip --production --dependencies",
|
|
9
|
+
"lint": "eslint",
|
|
10
|
+
"lint:fix": "eslint --fix",
|
|
11
|
+
"test:unit": "cross-env NODE_ENV=test borp",
|
|
12
|
+
"test:watch": "cross-env NODE_ENV=test node --watch --test",
|
|
13
|
+
"test:with-debug": "npm i --no-save --no-audit --no-fund debug@$DEBUG_VERSION && npm run test:unit",
|
|
14
|
+
"test-2.3": "cross-env DEBUG_VERSION=2.3 npm run test:with-debug",
|
|
15
|
+
"test-2.4": "cross-env DEBUG_VERSION=2.4 npm run test:with-debug",
|
|
16
|
+
"test-2.5": "cross-env DEBUG_VERSION=2.5 npm run test:with-debug",
|
|
17
|
+
"test-2.6": "cross-env DEBUG_VERSION=2.6 npm run test:with-debug",
|
|
18
|
+
"test-3.1": "cross-env DEBUG_VERSION=3.1 npm run test:with-debug",
|
|
19
|
+
"test-4.1": "cross-env DEBUG_VERSION=4.1 npm run test:with-debug",
|
|
20
|
+
"test-all": "npm run test-2.3 && npm run test-2.4 && npm run test-2.5 && npm run test-2.6 && npm run test-3.1 && npm run test-4.1",
|
|
21
|
+
"ci": "npm test",
|
|
22
|
+
"bench": "node benchmarks/runbench all",
|
|
23
|
+
"bench-basic": "node benchmarks/runbench basic",
|
|
24
|
+
"bench-object": "node benchmarks/runbench object",
|
|
25
|
+
"bench-deepobject": "node benchmarks/runbench deepobject",
|
|
26
|
+
"security:audit": "npm audit --audit-level=moderate",
|
|
27
|
+
"security:fix": "npm audit fix",
|
|
28
|
+
"security:snyk": "snyk test",
|
|
29
|
+
"security:check": "npm run security:audit && npm run security:snyk",
|
|
30
|
+
"security:validate": "node scripts/security-check.js",
|
|
31
|
+
"prepare": "npm run security:audit"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/json-douglas/pino-debugging.git"
|
|
36
|
+
},
|
|
37
|
+
"author": {
|
|
38
|
+
"name": "json douglas",
|
|
39
|
+
"url": "https://github.com/json-douglas"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/json-douglas/pino-debugging/issues"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/json-douglas/pino-debugging#readme",
|
|
45
|
+
"keywords": [
|
|
46
|
+
"pino",
|
|
47
|
+
"debug",
|
|
48
|
+
"fast",
|
|
49
|
+
"performance",
|
|
50
|
+
"debugging",
|
|
51
|
+
"logging",
|
|
52
|
+
"logger",
|
|
53
|
+
"security",
|
|
54
|
+
"production-ready",
|
|
55
|
+
"logfmt"
|
|
56
|
+
],
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"funding": {
|
|
59
|
+
"type": "opencollective",
|
|
60
|
+
"url": "https://opencollective.com/pino"
|
|
61
|
+
},
|
|
62
|
+
"security": {
|
|
63
|
+
"policy": "https://github.com/json-douglas/pino-debugging/security/policy",
|
|
64
|
+
"contact": "security@json-douglas.io"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"pino": "^10.1.0",
|
|
68
|
+
"debug-fnt": "^1.0.3"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"borp": "^0.21.0",
|
|
72
|
+
"cross-env": "^7.0.3",
|
|
73
|
+
"debug": "^4.4.3",
|
|
74
|
+
"eslint": "^9.38.0",
|
|
75
|
+
"fastbench": "^1.0.1",
|
|
76
|
+
"knip": "^5.1.2",
|
|
77
|
+
"neostandard": "^0.12.2",
|
|
78
|
+
"pump": "^3.0.0",
|
|
79
|
+
"split2": "^4.2.0",
|
|
80
|
+
"steed": "^1.1.3",
|
|
81
|
+
"through2": "^4.0.2"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Security validation script for pino-debugger
|
|
5
|
+
* Checks for common security issues and best practices
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs')
|
|
9
|
+
|
|
10
|
+
console.log('🔒 Running security validation for pino-debugger...\n')
|
|
11
|
+
|
|
12
|
+
// Check 1: Verify security documentation exists
|
|
13
|
+
function checkSecurityDocs () {
|
|
14
|
+
const requiredFiles = [
|
|
15
|
+
'SECURITY.md',
|
|
16
|
+
'CONTRIBUTING.md',
|
|
17
|
+
'CODE_OF_CONDUCT.md',
|
|
18
|
+
'docs/SECURITY_BEST_PRACTICES.md'
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const missing = requiredFiles.filter(file => !fs.existsSync(file))
|
|
22
|
+
|
|
23
|
+
if (missing.length === 0) {
|
|
24
|
+
console.log('✅ All security documentation files present')
|
|
25
|
+
return true
|
|
26
|
+
} else {
|
|
27
|
+
console.log('❌ Missing security documentation:', missing.join(', '))
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Check 2: Verify package.json security metadata
|
|
33
|
+
function checkPackageJsonSecurity () {
|
|
34
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'))
|
|
35
|
+
|
|
36
|
+
const hasSecurityScripts = pkg.scripts &&
|
|
37
|
+
pkg.scripts['security:audit'] &&
|
|
38
|
+
pkg.scripts['security:check']
|
|
39
|
+
|
|
40
|
+
const hasSecurityMetadata = pkg.security &&
|
|
41
|
+
pkg.security.policy &&
|
|
42
|
+
pkg.security.contact
|
|
43
|
+
|
|
44
|
+
if (hasSecurityScripts && hasSecurityMetadata) {
|
|
45
|
+
console.log('✅ Package.json has security scripts and metadata')
|
|
46
|
+
return true
|
|
47
|
+
} else {
|
|
48
|
+
console.log('❌ Package.json missing security configuration')
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check 3: Verify GitHub security templates (optional)
|
|
54
|
+
function checkGitHubTemplates () {
|
|
55
|
+
const requiredTemplates = [
|
|
56
|
+
'.github/ISSUE_TEMPLATE/bug_report.md',
|
|
57
|
+
'.github/ISSUE_TEMPLATE/feature_request.md',
|
|
58
|
+
'.github/PULL_REQUEST_TEMPLATE.md'
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
const optionalTemplates = [
|
|
62
|
+
'.github/workflows/security-simple.yml'
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
const missing = requiredTemplates.filter(file => !fs.existsSync(file))
|
|
66
|
+
const missingOptional = optionalTemplates.filter(file => !fs.existsSync(file))
|
|
67
|
+
|
|
68
|
+
if (missing.length === 0) {
|
|
69
|
+
console.log('✅ All required GitHub security templates present')
|
|
70
|
+
if (missingOptional.length > 0) {
|
|
71
|
+
console.log('ℹ️ Optional templates missing:', missingOptional.join(', '))
|
|
72
|
+
}
|
|
73
|
+
return true
|
|
74
|
+
} else {
|
|
75
|
+
console.log('❌ Missing required GitHub templates:', missing.join(', '))
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check 4: Verify Snyk configuration
|
|
81
|
+
function checkSnykConfig () {
|
|
82
|
+
if (fs.existsSync('.snyk')) {
|
|
83
|
+
console.log('✅ Snyk configuration file present')
|
|
84
|
+
return true
|
|
85
|
+
} else {
|
|
86
|
+
console.log('❌ Missing .snyk configuration file')
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Check 5: Verify no sensitive data in code
|
|
92
|
+
function checkSensitiveData () {
|
|
93
|
+
const sensitivePatterns = [
|
|
94
|
+
/password\s*=\s*['"][^'"]+['"]/i,
|
|
95
|
+
/api[_-]?key\s*=\s*['"][^'"]+['"]/i,
|
|
96
|
+
/secret\s*=\s*['"][^'"]+['"]/i,
|
|
97
|
+
/token\s*=\s*['"][^'"]+['"]/i
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
const filesToCheck = ['index.js', 'debug.js', 'test.js']
|
|
101
|
+
let foundSensitive = false
|
|
102
|
+
|
|
103
|
+
filesToCheck.forEach(file => {
|
|
104
|
+
if (fs.existsSync(file)) {
|
|
105
|
+
const content = fs.readFileSync(file, 'utf8')
|
|
106
|
+
sensitivePatterns.forEach(pattern => {
|
|
107
|
+
if (pattern.test(content)) {
|
|
108
|
+
console.log(`❌ Potential sensitive data found in ${file}`)
|
|
109
|
+
foundSensitive = true
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
if (!foundSensitive) {
|
|
116
|
+
console.log('✅ No sensitive data patterns found in source code')
|
|
117
|
+
return true
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check 6: Verify dependencies are up to date
|
|
124
|
+
function checkDependencyFreshness () {
|
|
125
|
+
try {
|
|
126
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'))
|
|
127
|
+
const lockExists = fs.existsSync('package-lock.json')
|
|
128
|
+
|
|
129
|
+
if (lockExists && pkg.dependencies) {
|
|
130
|
+
console.log('✅ Package lock file exists for reproducible builds')
|
|
131
|
+
return true
|
|
132
|
+
} else {
|
|
133
|
+
console.log('❌ Missing package-lock.json or dependencies')
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.log('❌ Error checking dependencies:', error.message)
|
|
138
|
+
return false
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Run all checks
|
|
143
|
+
async function runSecurityChecks () {
|
|
144
|
+
const results = [
|
|
145
|
+
checkSecurityDocs(),
|
|
146
|
+
checkPackageJsonSecurity(),
|
|
147
|
+
checkGitHubTemplates(),
|
|
148
|
+
checkSnykConfig(),
|
|
149
|
+
checkSensitiveData(),
|
|
150
|
+
checkDependencyFreshness()
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
const passed = results.filter(Boolean).length
|
|
154
|
+
const total = results.length
|
|
155
|
+
|
|
156
|
+
console.log(`\n📊 Security Check Results: ${passed}/${total} checks passed`)
|
|
157
|
+
|
|
158
|
+
if (passed === total) {
|
|
159
|
+
console.log('🎉 All security checks passed! Project is ready for improved Snyk score.')
|
|
160
|
+
process.exit(0)
|
|
161
|
+
} else {
|
|
162
|
+
console.log('⚠️ Some security checks failed. Please address the issues above.')
|
|
163
|
+
process.exit(1)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Run the checks
|
|
168
|
+
runSecurityChecks().catch(error => {
|
|
169
|
+
console.error('❌ Security check failed:', error)
|
|
170
|
+
process.exit(1)
|
|
171
|
+
})
|
package/test/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// pino-debugger must be required at the entry point, before other modules
|
|
4
|
+
const pinoDebug = require('../index.js')
|
|
5
|
+
const pino = require('pino')
|
|
6
|
+
const debug = require('../debug.js')
|
|
7
|
+
|
|
8
|
+
// Initialize pino-debugger with a pino logger instance
|
|
9
|
+
// All available options: auto, map, and skip
|
|
10
|
+
const logger = pino({ level: 'debug' })
|
|
11
|
+
pinoDebug(logger, {
|
|
12
|
+
// auto: automatically enable namespaces listed in map (default: true)
|
|
13
|
+
// If true: namespaces in map are automatically enabled for logging
|
|
14
|
+
// If false: only namespaces enabled via DEBUG env var will be logged
|
|
15
|
+
// Namespaces in map will still use their mapped log levels when enabled
|
|
16
|
+
// Example with auto: false - set DEBUG=test:app,test:module before running
|
|
17
|
+
// auto: true,
|
|
18
|
+
|
|
19
|
+
// map: associate debug namespaces with pino log levels
|
|
20
|
+
// Supports wildcards (*) in namespace patterns
|
|
21
|
+
// Available pino log levels: trace, debug, info, warn, error, fatal
|
|
22
|
+
map: {
|
|
23
|
+
'test:app': 'info', // Specific namespace -> info level
|
|
24
|
+
'test:module': 'debug', // Specific namespace -> debug level
|
|
25
|
+
'test:error': 'error', // Error-level logging
|
|
26
|
+
'test:warn': 'warn', // Warning-level logging
|
|
27
|
+
'test:trace': 'trace', // Trace-level logging
|
|
28
|
+
'test:critical': 'fatal', // Fatal-level logging
|
|
29
|
+
'test:util:*': 'debug', // Wildcard pattern -> debug level
|
|
30
|
+
'test:sub:*': 'trace', // Another wildcard pattern
|
|
31
|
+
'test:*': 'trace' // Catch-all pattern (must be last due to precision sorting)
|
|
32
|
+
},
|
|
33
|
+
levels: ['info', 'warn', 'error', 'fatal', 'trace', 'debug'],
|
|
34
|
+
// format: specify the output format for debug-fmt
|
|
35
|
+
// Available formats: 'logfmt' (default), 'json', 'pretty'
|
|
36
|
+
format: 'logfmt',
|
|
37
|
+
// skip: array of namespaces to disable/skip
|
|
38
|
+
// Equivalent to prefixing namespaces with '-' in DEBUG env var
|
|
39
|
+
skip: [
|
|
40
|
+
'test:disabled', // This namespace will not be logged
|
|
41
|
+
'test:noisy:*' // Skip all noisy sub-namespaces
|
|
42
|
+
]
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// Test basic debug logging with all log levels
|
|
46
|
+
console.log('\n=== Basic Debug Logging (All Levels) ===')
|
|
47
|
+
const debugApp = debug('test:app')
|
|
48
|
+
debugApp('This is an INFO level message from test:app')
|
|
49
|
+
|
|
50
|
+
const debugModule = debug('test:module')
|
|
51
|
+
debugModule('This is a DEBUG level message from test:module')
|
|
52
|
+
|
|
53
|
+
const debugError = debug('test:error')
|
|
54
|
+
debugError('This is an ERROR level message from test:error')
|
|
55
|
+
|
|
56
|
+
const debugWarn = debug('test:warn')
|
|
57
|
+
debugWarn('This is a WARN level message from test:warn')
|
|
58
|
+
|
|
59
|
+
const debugTrace = debug('test:trace')
|
|
60
|
+
debugTrace('This is a TRACE level message from test:trace')
|
|
61
|
+
|
|
62
|
+
const debugFatal = debug('test:critical')
|
|
63
|
+
debugFatal('This is a FATAL level message from test:critical')
|
|
64
|
+
|
|
65
|
+
const debugOther = debug('test:other')
|
|
66
|
+
debugOther('This is a TRACE level message from test:other (matches test:* pattern)')
|
|
67
|
+
|
|
68
|
+
// Test wildcard patterns
|
|
69
|
+
const debugUtil = debug('test:util:helper')
|
|
70
|
+
debugUtil('This is a DEBUG level message from test:util:helper (matches test:util:*)')
|
|
71
|
+
|
|
72
|
+
const debugSub = debug('test:sub:component')
|
|
73
|
+
debugSub('This is a TRACE level message from test:sub:component (matches test:sub:*)')
|
|
74
|
+
|
|
75
|
+
// Test skipped namespaces (should not log)
|
|
76
|
+
const debugDisabled = debug('test:disabled')
|
|
77
|
+
debugDisabled('This message should NOT appear (namespace is skipped)')
|
|
78
|
+
|
|
79
|
+
const debugNoisy = debug('test:noisy:log')
|
|
80
|
+
debugNoisy('This message should NOT appear (test:noisy:* is skipped)')
|
|
81
|
+
|
|
82
|
+
// Test debug with format strings
|
|
83
|
+
console.log('\n=== Debug with Format Strings ===')
|
|
84
|
+
debugApp('User %s logged in with id %d', 'alice', 123)
|
|
85
|
+
debugModule('Processing %j', { action: 'test', value: 42 })
|
|
86
|
+
|
|
87
|
+
// Test debug.enabled
|
|
88
|
+
console.log('\n=== Debug Enabled Check ===')
|
|
89
|
+
console.log('test:app enabled:', debug('test:app').enabled)
|
|
90
|
+
console.log('test:disabled enabled:', debug('test:disabled').enabled)
|
|
91
|
+
|
|
92
|
+
// Test debug.extend
|
|
93
|
+
console.log('\n=== Debug Extend ===')
|
|
94
|
+
const debugAppSub = debugApp.extend('submodule')
|
|
95
|
+
debugAppSub('This is a message from test:app:submodule')
|
|
96
|
+
|
|
97
|
+
console.log('\n=== Test Complete ===')
|
|
98
|
+
console.log('\nNote: To test auto: false, change auto to false and run:')
|
|
99
|
+
console.log(' DEBUG=test:app,test:module node test.js')
|
|
100
|
+
console.log('Only explicitly enabled namespaces will be logged.')
|
package/test.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// pino-debugger must be required at the entry point, before other modules
|
|
4
|
+
const pinoDebug = require('./index.js')
|
|
5
|
+
const pino = require('pino')
|
|
6
|
+
|
|
7
|
+
// Initialize pino-debugger with a pino logger instance
|
|
8
|
+
// All available options: auto, map, and skip
|
|
9
|
+
const logger = pino({ level: 'debug' })
|
|
10
|
+
pinoDebug(logger, {
|
|
11
|
+
// auto: automatically enable namespaces listed in map (default: true)
|
|
12
|
+
// If true: namespaces in map are automatically enabled for logging
|
|
13
|
+
// If false: only namespaces enabled via DEBUG env var will be logged
|
|
14
|
+
// Namespaces in map will still use their mapped log levels when enabled
|
|
15
|
+
// Example with auto: false - set DEBUG=test:app,test:module before running
|
|
16
|
+
// auto: true,
|
|
17
|
+
|
|
18
|
+
// map: associate debug namespaces with pino log levels
|
|
19
|
+
// Supports wildcards (*) in namespace patterns
|
|
20
|
+
// Available pino log levels: trace, debug, info, warn, error, fatal
|
|
21
|
+
map: {
|
|
22
|
+
'test:app': 'info', // Specific namespace -> info level
|
|
23
|
+
'test:module': 'debug', // Specific namespace -> debug level
|
|
24
|
+
'test:error': 'error', // Error-level logging
|
|
25
|
+
'test:warn': 'warn', // Warning-level logging
|
|
26
|
+
'test:trace': 'trace', // Trace-level logging
|
|
27
|
+
'test:critical': 'fatal', // Fatal-level logging
|
|
28
|
+
'test:util:*': 'debug', // Wildcard pattern -> debug level
|
|
29
|
+
'test:sub:*': 'trace', // Another wildcard pattern
|
|
30
|
+
'test:*': 'trace' // Catch-all pattern (must be last due to precision sorting)
|
|
31
|
+
},
|
|
32
|
+
levels: ['info', 'warn', 'error', 'fatal', 'trace', 'debug'],
|
|
33
|
+
// format: specify the output format for debug-fmt
|
|
34
|
+
// Available formats: 'logfmt' (default), 'json', 'pretty'
|
|
35
|
+
format: 'logfmt',
|
|
36
|
+
// skip: array of namespaces to disable/skip
|
|
37
|
+
// Equivalent to prefixing namespaces with '-' in DEBUG env var
|
|
38
|
+
skip: [
|
|
39
|
+
'test:disabled', // This namespace will not be logged
|
|
40
|
+
'test:noisy:*' // Skip all noisy sub-namespaces
|
|
41
|
+
]
|
|
42
|
+
})
|