@crimsonsunset/jsg-logger 1.7.13 → 1.7.15
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/README.md +116 -0
- package/config/config-manager.js +26 -0
- package/config/default-config.json +4 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js +5 -0
- package/devtools/dist/__vite-browser-external-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW-2Ng8QIWW.js.map +1 -0
- package/devtools/dist/panel-entry-Ahej53sX-y0jCvGoU-BGR5GUGQ-B-CAdAd3-DipRT8xT-CSMwqnO2-CHbiC4Qe-BRrWXqYD-CNcJekPg.js +13932 -0
- package/devtools/dist/panel-entry-Ahej53sX-y0jCvGoU-BGR5GUGQ-B-CAdAd3-DipRT8xT-CSMwqnO2-CHbiC4Qe-BRrWXqYD-CNcJekPg.js.map +1 -0
- package/devtools/dist/panel-entry-B0ZWdsQY-DQdquw3J-TpkzsLdj-BGvdXuoS-CzTJvBQl-CAQNpg2W-Bo2gswMb-CAJV5DP5-DZe7oWlk-tDqwNUld.js +13923 -0
- package/devtools/dist/panel-entry-B0ZWdsQY-DQdquw3J-TpkzsLdj-BGvdXuoS-CzTJvBQl-CAQNpg2W-Bo2gswMb-CAJV5DP5-DZe7oWlk-tDqwNUld.js.map +1 -0
- package/devtools/dist/panel-entry-B2MhZ3gp.js +13975 -0
- package/devtools/dist/panel-entry-B2MhZ3gp.js.map +1 -0
- package/devtools/dist/{panel-entry-BZ56bT66-BMyD75mc.js → panel-entry-BZ56bT66-BMyD75mc-BxfcB-io-DLFBg4X2-By57n0cz-DG9FfyPU-tsDeIORn-Brgs9eZh-C1aTwqVx-Bga5v200-D2uIBkta-DFygDOuM-CiZQ0ZWs-CK-Qy7JF-3_LfnrLj-C80pq-Ox-BAydVBl9.js} +4 -4
- package/devtools/dist/panel-entry-BZ56bT66-BMyD75mc-BxfcB-io-DLFBg4X2-By57n0cz-DG9FfyPU-tsDeIORn-Brgs9eZh-C1aTwqVx-Bga5v200-D2uIBkta-DFygDOuM-CiZQ0ZWs-CK-Qy7JF-3_LfnrLj-C80pq-Ox-BAydVBl9.js.map +1 -0
- package/devtools/dist/panel-entry-BaBkkSt6-B3YoMX06.js +13963 -0
- package/devtools/dist/panel-entry-BaBkkSt6-B3YoMX06.js.map +1 -0
- package/devtools/dist/panel-entry-CIG0rw0G-C23A9sjU-CbDuened.js +13957 -0
- package/devtools/dist/panel-entry-CIG0rw0G-C23A9sjU-CbDuened.js.map +1 -0
- package/devtools/dist/panel-entry-CLDrp2P4-BhE5Qmzo-DsrDp_aW-D77vFWhc-D0p-3Vck-juqy3fYf-Dla5eR-o-CER385zO-3kQqst6Z-mEXeTQxs-XDwY_WUW-CcUUttdq-BGVY77mY.js +13914 -0
- package/devtools/dist/panel-entry-CLDrp2P4-BhE5Qmzo-DsrDp_aW-D77vFWhc-D0p-3Vck-juqy3fYf-Dla5eR-o-CER385zO-3kQqst6Z-mEXeTQxs-XDwY_WUW-CcUUttdq-BGVY77mY.js.map +1 -0
- package/devtools/dist/panel-entry-Car1txqz-Cujk5tL9-pWwzfz1C-C_CMO2R5-BtcT6buV-DEh6fx7S-BLtwgJNF-CUuTgFqX.js +13935 -0
- package/devtools/dist/panel-entry-Car1txqz-Cujk5tL9-pWwzfz1C-C_CMO2R5-BtcT6buV-DEh6fx7S-BLtwgJNF-CUuTgFqX.js.map +1 -0
- package/devtools/dist/panel-entry-CdHyTMuR-wqllnGMv-CJFeg7x9-C7mRB5fj-DOgQaLRi-yYTqC4-t-DKUNOg6F-BtruRO_z-BDQrJIZQ-ByHq-LMj-Drlk5OTb-BAoinR4q-CD8VtN79-Cidg8klg-CA9PGoiF.js +13728 -0
- package/devtools/dist/panel-entry-CdHyTMuR-wqllnGMv-CJFeg7x9-C7mRB5fj-DOgQaLRi-yYTqC4-t-DKUNOg6F-BtruRO_z-BDQrJIZQ-ByHq-LMj-Drlk5OTb-BAoinR4q-CD8VtN79-Cidg8klg-CA9PGoiF.js.map +1 -0
- package/devtools/dist/panel-entry-D53S3yYJ-DlRCzJ0q-BnWPSxII-B57eqdYD-CRpb7P7m-CSgQ8r4U-DqjeAoTP.js +13935 -0
- package/devtools/dist/panel-entry-D53S3yYJ-DlRCzJ0q-BnWPSxII-B57eqdYD-CRpb7P7m-CSgQ8r4U-DqjeAoTP.js.map +1 -0
- package/devtools/dist/panel-entry-D6EQIVsV-51lrmGiZ-D4qVD_00-DVb1ySI7-C_RfHhv5-D78tUI3_.js +13945 -0
- package/devtools/dist/panel-entry-D6EQIVsV-51lrmGiZ-D4qVD_00-DVb1ySI7-C_RfHhv5-D78tUI3_.js.map +1 -0
- package/devtools/dist/{panel-entry-Da9n85v7.js → panel-entry-Da9n85v7-C6Gam2oq-DDT89MNj-D9ZqvcEM-Dx--LZLa-BJiXK46m-DGuagWzT-B6evq62k-Cj2QcsAJ-BnxooYWW-D4oxy7MQ-g1-2DT91-DESRmxtW-BFO1EmVx-MWoTuzW5-Cg1SKwet.js} +4 -4
- package/devtools/dist/panel-entry-Da9n85v7-C6Gam2oq-DDT89MNj-D9ZqvcEM-Dx--LZLa-BJiXK46m-DGuagWzT-B6evq62k-Cj2QcsAJ-BnxooYWW-D4oxy7MQ-g1-2DT91-DESRmxtW-BFO1EmVx-MWoTuzW5-Cg1SKwet.js.map +1 -0
- package/devtools/dist/panel-entry-DeLbn5Tk-P7ZtOAd3-DXeez3fy-BFxPfyZi-9L9N-1f8-DzO_hXuM-CWXuuiJk-CI3ufk2T-CP3JflFQ-CLoczwy1-D7ukr7PE-DbMhopxi-BHxIMhDL-CDnadrxB.js +13999 -0
- package/devtools/dist/panel-entry-DeLbn5Tk-P7ZtOAd3-DXeez3fy-BFxPfyZi-9L9N-1f8-DzO_hXuM-CWXuuiJk-CI3ufk2T-CP3JflFQ-CLoczwy1-D7ukr7PE-DbMhopxi-BHxIMhDL-CDnadrxB.js.map +1 -0
- package/devtools/dist/panel-entry-Dh3i-JKj-D7NSYIQS-C_qI61WQ-BfJ0BW16-Df40_Q6R.js +13951 -0
- package/devtools/dist/panel-entry-Dh3i-JKj-D7NSYIQS-C_qI61WQ-BfJ0BW16-Df40_Q6R.js.map +1 -0
- package/devtools/dist/panel-entry-DlWAx2yA-vZadFV4d-DTvClgVl-zRu1NJo4-rPRjTg0e-dbBSWeq3-jx9KYEq_-B3sEcSWI-DeCc9Glr-02P4pIqr-CrzX1Fsr-C1C-Fcde.js +13921 -0
- package/devtools/dist/panel-entry-DlWAx2yA-vZadFV4d-DTvClgVl-zRu1NJo4-rPRjTg0e-dbBSWeq3-jx9KYEq_-B3sEcSWI-DeCc9Glr-02P4pIqr-CrzX1Fsr-C1C-Fcde.js.map +1 -0
- package/devtools/dist/{panel-entry-DzGsV7s--DzGsV7s--DzGsV7s-.js → panel-entry-DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s-.js} +1 -1
- package/devtools/dist/panel-entry-DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s--DzGsV7s-.js.map +1 -0
- package/devtools/dist/panel-entry-F_czAD5m-haMWJ-NK-CsYx2f8v-CczoKRsz-CIS8-qZe-F0ks_Y8t-CZBpt1gj-QmZJhT5N-460P-RpL-CKLofb-z-DEXl2ipp.js +13921 -0
- package/devtools/dist/panel-entry-F_czAD5m-haMWJ-NK-CsYx2f8v-CczoKRsz-CIS8-qZe-F0ks_Y8t-CZBpt1gj-QmZJhT5N-460P-RpL-CKLofb-z-DEXl2ipp.js.map +1 -0
- package/devtools/dist/panel-entry-L66PnOAy-CSPip1Cq-DIdgAB36-D56Z9rwz.js +13957 -0
- package/devtools/dist/panel-entry-L66PnOAy-CSPip1Cq-DIdgAB36-D56Z9rwz.js.map +1 -0
- package/devtools/dist/panel-entry.js +449 -193
- package/devtools/dist/panel-entry.js.map +1 -1
- package/docs/roadmap.md +5 -0
- package/examples/advanced-config.json +8 -0
- package/formatters/browser-formatter.js +5 -1
- package/formatters/cli-formatter.js +7 -1
- package/formatters/server-formatter.js +7 -3
- package/index.js +112 -7
- package/package.json +1 -1
- package/utils/redaction.js +51 -0
- package/devtools/dist/panel-entry-BZ56bT66-BMyD75mc.js.map +0 -1
- package/devtools/dist/panel-entry-Da9n85v7.js.map +0 -1
- package/devtools/dist/panel-entry-DzGsV7s--DzGsV7s--DzGsV7s-.js.map +0 -1
package/docs/roadmap.md
CHANGED
|
@@ -435,6 +435,11 @@ Console filtering updates
|
|
|
435
435
|
|
|
436
436
|
### **🔮 Future Enhancements**
|
|
437
437
|
|
|
438
|
+
#### **Component Management** (Future)
|
|
439
|
+
- [ ] **Component removal notification** - Subscribe to component removal events (currently only addition events are supported)
|
|
440
|
+
- [ ] **Component lifecycle tracking** - Track when components are created and removed
|
|
441
|
+
- **Note:** Component addition notifications are implemented. Removal notifications are deferred for future enhancement (see TODO in `index.js:817`)
|
|
442
|
+
|
|
438
443
|
#### **Advanced Filtering** (Phase 6.5)
|
|
439
444
|
- [ ] **File-level controls** - Panel interface for file overrides
|
|
440
445
|
- [ ] **Search filtering** - Filter logs by message content
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"jsonPayload": true,
|
|
17
17
|
"stackTrace": true
|
|
18
18
|
},
|
|
19
|
+
"redact": {
|
|
20
|
+
"paths": ["password", "token", "*key", "*secret", "*apiKey", "*api_key"],
|
|
21
|
+
"censor": "[REDACTED]"
|
|
22
|
+
},
|
|
19
23
|
"components": {
|
|
20
24
|
"core": {
|
|
21
25
|
"emoji": "🎯",
|
|
@@ -116,6 +120,10 @@
|
|
|
116
120
|
"display": {
|
|
117
121
|
"jsonPayload": true,
|
|
118
122
|
"stackTrace": true
|
|
123
|
+
},
|
|
124
|
+
"redact": {
|
|
125
|
+
"paths": ["password", "token", "*key", "*secret"],
|
|
126
|
+
"censor": "***"
|
|
119
127
|
}
|
|
120
128
|
},
|
|
121
129
|
"src/database/*.js": {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {configManager} from '../config/config-manager.js';
|
|
8
|
+
import {redactValue} from '../utils/redaction.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Create browser console formatter for a specific component
|
|
@@ -28,6 +29,7 @@ export const createBrowserFormatter = (componentName, logStore = null) => {
|
|
|
28
29
|
const component = configManager.getComponentConfig(componentName, filePath);
|
|
29
30
|
const level = configManager.getLevelConfig(logData.level);
|
|
30
31
|
const displayConfig = configManager.getDisplayConfig(filePath);
|
|
32
|
+
const redactConfig = configManager.getRedactConfig(filePath);
|
|
31
33
|
|
|
32
34
|
// Check if this log should be displayed based on effective level
|
|
33
35
|
const effectiveLevel = configManager.getEffectiveLevel(componentName, filePath);
|
|
@@ -84,7 +86,8 @@ export const createBrowserFormatter = (componentName, logStore = null) => {
|
|
|
84
86
|
if (displayConfig.jsonPayload) {
|
|
85
87
|
const contextData = extractContextData(logData);
|
|
86
88
|
if (Object.keys(contextData).length > 0) {
|
|
87
|
-
|
|
89
|
+
const redactedData = redactValue(contextData, redactConfig);
|
|
90
|
+
displayContextData(redactedData);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
@@ -158,6 +161,7 @@ function extractContextData(logData) {
|
|
|
158
161
|
return contextData;
|
|
159
162
|
}
|
|
160
163
|
|
|
164
|
+
|
|
161
165
|
/**
|
|
162
166
|
* Display context data with tree-like structure
|
|
163
167
|
* @param {Object} contextData - Context data to display
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { LEVEL_SCHEME } from '../config/component-schemes.js';
|
|
7
7
|
import { configManager } from '../config/config-manager.js';
|
|
8
|
+
import { redactValue } from '../utils/redaction.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Format a value for display in context tree
|
|
@@ -27,6 +28,7 @@ const formatValue = (value) => {
|
|
|
27
28
|
return String(value);
|
|
28
29
|
};
|
|
29
30
|
|
|
31
|
+
|
|
30
32
|
/**
|
|
31
33
|
* Create CLI formatter with context data support
|
|
32
34
|
* @returns {Object} Stream-like object for Pino
|
|
@@ -62,10 +64,14 @@ export const createCLIFormatter = () => {
|
|
|
62
64
|
const contextKeys = Object.keys(log).filter(key => !internalFields.includes(key));
|
|
63
65
|
|
|
64
66
|
if (contextKeys.length > 0) {
|
|
67
|
+
// Get redact config and apply redaction
|
|
68
|
+
const redactConfig = configManager.getRedactConfig();
|
|
69
|
+
const redactedLog = redactValue(log, redactConfig);
|
|
70
|
+
|
|
65
71
|
contextKeys.forEach((key, index) => {
|
|
66
72
|
const isLast = index === contextKeys.length - 1;
|
|
67
73
|
const prefix = isLast ? ' └─' : ' ├─';
|
|
68
|
-
const value = formatValue(
|
|
74
|
+
const value = formatValue(redactedLog[key]);
|
|
69
75
|
console.log(`${prefix} ${key}: ${value}`);
|
|
70
76
|
});
|
|
71
77
|
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Structured JSON output for production logging and log aggregation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import {configManager} from '../config/config-manager.js';
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Create server formatter (structured JSON)
|
|
8
10
|
* @returns {null} No custom formatter - uses Pino's default JSON output
|
|
@@ -18,6 +20,8 @@ export const createServerFormatter = () => {
|
|
|
18
20
|
* @returns {Object} Pino configuration for server environments
|
|
19
21
|
*/
|
|
20
22
|
export const getServerConfig = () => {
|
|
23
|
+
const redactConfig = configManager.getRedactConfig();
|
|
24
|
+
|
|
21
25
|
return {
|
|
22
26
|
level: 'info', // More conservative logging in production
|
|
23
27
|
formatters: {
|
|
@@ -33,10 +37,10 @@ export const getServerConfig = () => {
|
|
|
33
37
|
};
|
|
34
38
|
}
|
|
35
39
|
},
|
|
36
|
-
// Redact sensitive information in production
|
|
40
|
+
// Redact sensitive information in production (configurable)
|
|
37
41
|
redact: {
|
|
38
|
-
paths: ['password', 'token', 'key', 'secret'],
|
|
39
|
-
censor: '[REDACTED]'
|
|
42
|
+
paths: redactConfig.paths.length > 0 ? redactConfig.paths : ['password', 'token', 'key', 'secret'],
|
|
43
|
+
censor: redactConfig.censor || '[REDACTED]'
|
|
40
44
|
}
|
|
41
45
|
};
|
|
42
46
|
};
|
package/index.js
CHANGED
|
@@ -57,6 +57,7 @@ class JSGLogger {
|
|
|
57
57
|
this.environment = null; // Will be set after config loads
|
|
58
58
|
this.initialized = false;
|
|
59
59
|
this.components = {}; // Auto-discovery getters
|
|
60
|
+
this.componentSubscribers = []; // Subscribers for component change events
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
/**
|
|
@@ -75,6 +76,7 @@ class JSGLogger {
|
|
|
75
76
|
// Make runtime controls available globally in browser for debugging
|
|
76
77
|
if (isBrowser() && typeof window !== 'undefined' && JSGLogger._enhancedLoggers?.controls) {
|
|
77
78
|
window.JSG_Logger = JSGLogger._enhancedLoggers.controls;
|
|
79
|
+
window.__JSG_Logger_Enhanced__ = JSGLogger._enhancedLoggers;
|
|
78
80
|
}
|
|
79
81
|
} else if (hasOptions) {
|
|
80
82
|
// Instance exists but new options provided - reinitialize
|
|
@@ -84,6 +86,7 @@ class JSGLogger {
|
|
|
84
86
|
// (same as getInstanceSync behavior)
|
|
85
87
|
if (isBrowser() && typeof window !== 'undefined' && JSGLogger._enhancedLoggers?.controls) {
|
|
86
88
|
window.JSG_Logger = JSGLogger._enhancedLoggers.controls;
|
|
89
|
+
window.__JSG_Logger_Enhanced__ = JSGLogger._enhancedLoggers;
|
|
87
90
|
}
|
|
88
91
|
}
|
|
89
92
|
|
|
@@ -92,21 +95,62 @@ class JSGLogger {
|
|
|
92
95
|
|
|
93
96
|
/**
|
|
94
97
|
* Get singleton instance synchronously (for environments without async support)
|
|
98
|
+
* Checks window.JSG_Logger first to ensure singleton works across separate bundles
|
|
95
99
|
* @param {Object} options - Initialization options (only used on first call)
|
|
96
100
|
* @returns {Object} Enhanced logger exports with controls API
|
|
97
101
|
*/
|
|
98
102
|
static getInstanceSync(options = {}) {
|
|
99
103
|
const hasOptions = options && Object.keys(options).length > 0;
|
|
104
|
+
|
|
105
|
+
// If options are provided, we need to reinitialize even if global instance exists
|
|
106
|
+
// This ensures config changes (like devtools.enabled) are applied
|
|
107
|
+
if (hasOptions) {
|
|
108
|
+
// Reinitialize with new options - this will update the global references
|
|
109
|
+
if (!JSGLogger._instance) {
|
|
110
|
+
JSGLogger._instance = new JSGLogger();
|
|
111
|
+
}
|
|
112
|
+
JSGLogger._enhancedLoggers = JSGLogger._instance.initSync(options);
|
|
113
|
+
|
|
114
|
+
// Update global references after reinitialization
|
|
115
|
+
if (isBrowser() && typeof window !== 'undefined' && JSGLogger._enhancedLoggers?.controls) {
|
|
116
|
+
window.JSG_Logger = JSGLogger._enhancedLoggers.controls;
|
|
117
|
+
window.__JSG_Logger_Enhanced__ = JSGLogger._enhancedLoggers;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return JSGLogger._enhancedLoggers;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// No options provided - check window.JSG_Logger first to ensure singleton works across bundles
|
|
124
|
+
// This is critical when devtools bundle loads separately from main app
|
|
125
|
+
if (isBrowser() && typeof window !== 'undefined' && window.JSG_Logger) {
|
|
126
|
+
// If enhanced loggers reference exists, use it (preferred)
|
|
127
|
+
if (window.__JSG_Logger_Enhanced__) {
|
|
128
|
+
return window.__JSG_Logger_Enhanced__;
|
|
129
|
+
}
|
|
130
|
+
// Fallback: reconstruct enhanced loggers from controls object
|
|
131
|
+
// This handles cases where __JSG_Logger_Enhanced__ wasn't set
|
|
132
|
+
const globalControls = window.JSG_Logger;
|
|
133
|
+
return {
|
|
134
|
+
...globalControls,
|
|
135
|
+
controls: globalControls,
|
|
136
|
+
getComponent: globalControls.getComponent,
|
|
137
|
+
getInstanceSync: JSGLogger.getInstanceSync.bind(JSGLogger),
|
|
138
|
+
getInstance: JSGLogger.getInstance.bind(JSGLogger),
|
|
139
|
+
logPerformance: JSGLogger.logPerformance.bind(JSGLogger),
|
|
140
|
+
JSGLogger: JSGLogger
|
|
141
|
+
};
|
|
142
|
+
}
|
|
100
143
|
|
|
144
|
+
// No options and no global instance - first time initialization
|
|
101
145
|
if (!JSGLogger._instance) {
|
|
102
|
-
// First time initialization
|
|
103
146
|
JSGLogger._instance = new JSGLogger();
|
|
104
147
|
JSGLogger._enhancedLoggers = JSGLogger._instance.initSync(options);
|
|
105
|
-
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
|
|
149
|
+
// Make runtime controls available globally in browser for debugging
|
|
150
|
+
if (isBrowser() && typeof window !== 'undefined' && JSGLogger._enhancedLoggers?.controls) {
|
|
151
|
+
window.JSG_Logger = JSGLogger._enhancedLoggers.controls;
|
|
152
|
+
window.__JSG_Logger_Enhanced__ = JSGLogger._enhancedLoggers;
|
|
153
|
+
}
|
|
110
154
|
}
|
|
111
155
|
|
|
112
156
|
return JSGLogger._enhancedLoggers;
|
|
@@ -282,6 +326,19 @@ class JSGLogger {
|
|
|
282
326
|
|
|
283
327
|
// Create auto-discovery getters (eager)
|
|
284
328
|
this._createAutoDiscoveryGetters();
|
|
329
|
+
|
|
330
|
+
// Notify component subscribers after reinitialization (if components changed)
|
|
331
|
+
// This ensures panel sees components created during reinit, not just via getComponent()
|
|
332
|
+
if (this.componentSubscribers.length > 0) {
|
|
333
|
+
const currentComponents = Object.keys(this.loggers);
|
|
334
|
+
this.componentSubscribers.forEach(callback => {
|
|
335
|
+
try {
|
|
336
|
+
callback(currentComponents);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
metaError('Component subscriber error:', error);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
285
342
|
|
|
286
343
|
this.initialized = true;
|
|
287
344
|
|
|
@@ -494,7 +551,25 @@ class JSGLogger {
|
|
|
494
551
|
},
|
|
495
552
|
|
|
496
553
|
// Component controls
|
|
497
|
-
listComponents: () =>
|
|
554
|
+
listComponents: () => Object.keys(this.loggers),
|
|
555
|
+
subscribeToComponents: (callback) => {
|
|
556
|
+
this.componentSubscribers.push(callback);
|
|
557
|
+
// Immediately call callback with current component list (don't wait for changes)
|
|
558
|
+
// This ensures panel sees components created during reinitialization
|
|
559
|
+
const currentComponents = Object.keys(this.loggers);
|
|
560
|
+
try {
|
|
561
|
+
callback(currentComponents);
|
|
562
|
+
} catch (error) {
|
|
563
|
+
this.loggers.core?.error('Component subscriber error (initial call):', error);
|
|
564
|
+
}
|
|
565
|
+
// Return unsubscribe function
|
|
566
|
+
return () => {
|
|
567
|
+
const index = this.componentSubscribers.indexOf(callback);
|
|
568
|
+
if (index > -1) {
|
|
569
|
+
this.componentSubscribers.splice(index, 1);
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
},
|
|
498
573
|
enableDebugMode: () => {
|
|
499
574
|
Object.keys(this.loggers).forEach(component => {
|
|
500
575
|
if (this.loggers[component]) {
|
|
@@ -801,6 +876,26 @@ class JSGLogger {
|
|
|
801
876
|
if (camelName !== componentName) {
|
|
802
877
|
this.components[camelName] = () => this.getComponent(componentName);
|
|
803
878
|
}
|
|
879
|
+
|
|
880
|
+
// Notify component subscribers of the change (emit on every add, not deduplicated)
|
|
881
|
+
// TODO: Add component removal notification support (future enhancement)
|
|
882
|
+
const currentComponents = Object.keys(this.loggers);
|
|
883
|
+
if (this.componentSubscribers.length > 0) {
|
|
884
|
+
if (this.loggers.core) {
|
|
885
|
+
this.loggers.core.debug(`Notifying ${this.componentSubscribers.length} subscribers of component change`, {
|
|
886
|
+
component: componentName,
|
|
887
|
+
totalComponents: currentComponents.length,
|
|
888
|
+
components: currentComponents
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
this.componentSubscribers.forEach(callback => {
|
|
893
|
+
try {
|
|
894
|
+
callback(currentComponents);
|
|
895
|
+
} catch (error) {
|
|
896
|
+
this.loggers.core?.error('Component subscriber error:', error);
|
|
897
|
+
}
|
|
898
|
+
});
|
|
804
899
|
}
|
|
805
900
|
|
|
806
901
|
return this.loggers[componentName];
|
|
@@ -858,10 +953,18 @@ class JSGLogger {
|
|
|
858
953
|
|
|
859
954
|
/**
|
|
860
955
|
* Get singleton controls without triggering initialization
|
|
956
|
+
* Checks window.JSG_Logger first to ensure singleton works across separate bundles
|
|
861
957
|
* Returns the controls object from the current singleton instance if it exists
|
|
862
958
|
* @returns {Object|null} Controls object or null if singleton not initialized
|
|
863
959
|
*/
|
|
864
960
|
static getControls() {
|
|
961
|
+
// Check window.JSG_Logger first to ensure singleton works across bundles
|
|
962
|
+
// This is critical when devtools bundle loads separately from main app
|
|
963
|
+
if (isBrowser() && typeof window !== 'undefined' && window.JSG_Logger) {
|
|
964
|
+
return window.JSG_Logger;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// Fall back to local instance if global doesn't exist
|
|
865
968
|
return JSGLogger._enhancedLoggers?.controls || null;
|
|
866
969
|
}
|
|
867
970
|
}
|
|
@@ -871,8 +974,10 @@ class JSGLogger {
|
|
|
871
974
|
const enhancedLoggers = JSGLogger.getInstanceSync();
|
|
872
975
|
|
|
873
976
|
// Make runtime controls available globally in browser for debugging
|
|
977
|
+
// Also store enhanced loggers reference so getInstanceSync() can access it across bundles
|
|
874
978
|
if (isBrowser() && typeof window !== 'undefined') {
|
|
875
979
|
window.JSG_Logger = enhancedLoggers.controls;
|
|
980
|
+
window.__JSG_Logger_Enhanced__ = enhancedLoggers;
|
|
876
981
|
}
|
|
877
982
|
|
|
878
983
|
// Add static methods to the enhanced loggers for convenience
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crimsonsunset/jsg-logger",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Multi-environment logger with smart detection, file-level overrides, and beautiful console formatting. Test it live: https://logger.joesangiorgio.com/",
|
|
6
6
|
"main": "index.js",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redaction utility functions for sensitive data protection
|
|
3
|
+
* Used by browser, CLI, and server formatters
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check if a key should be redacted based on patterns
|
|
8
|
+
* @param {string} key - Key to check
|
|
9
|
+
* @param {string[]} paths - Array of patterns (exact match or wildcard like *key)
|
|
10
|
+
* @returns {boolean} Whether key should be redacted
|
|
11
|
+
*/
|
|
12
|
+
export function shouldRedactKey(key, paths) {
|
|
13
|
+
return paths.some(pattern => {
|
|
14
|
+
if (pattern.startsWith('*')) {
|
|
15
|
+
const suffix = pattern.slice(1).toLowerCase();
|
|
16
|
+
return key.toLowerCase().endsWith(suffix);
|
|
17
|
+
}
|
|
18
|
+
return key.toLowerCase() === pattern.toLowerCase();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Redact sensitive values from an object based on key patterns
|
|
24
|
+
* @param {*} value - Value to redact (object, array, or primitive)
|
|
25
|
+
* @param {Object} redactConfig - Redaction configuration with paths and censor
|
|
26
|
+
* @returns {*} Redacted value
|
|
27
|
+
*/
|
|
28
|
+
export function redactValue(value, redactConfig) {
|
|
29
|
+
if (!redactConfig || !redactConfig.paths || redactConfig.paths.length === 0) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
34
|
+
const redacted = {};
|
|
35
|
+
for (const [key, val] of Object.entries(value)) {
|
|
36
|
+
if (shouldRedactKey(key, redactConfig.paths)) {
|
|
37
|
+
redacted[key] = redactConfig.censor || '[REDACTED]';
|
|
38
|
+
} else {
|
|
39
|
+
redacted[key] = redactValue(val, redactConfig);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return redacted;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
return value.map(item => redactValue(item, redactConfig));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
|