debug-better 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/LICENSE +21 -0
- package/README.md +400 -0
- package/dist/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +171 -0
- package/dist/browser.js.map +1 -0
- package/dist/common.d.ts +14 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +258 -0
- package/dist/common.js.map +1 -0
- package/dist/filter.d.ts +64 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +182 -0
- package/dist/filter.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +9 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +177 -0
- package/dist/node.js.map +1 -0
- package/dist/types.d.ts +165 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
- package/src/browser.ts +199 -0
- package/src/common.ts +306 -0
- package/src/filter.ts +204 -0
- package/src/index.ts +23 -0
- package/src/node.ts +161 -0
- package/src/types.ts +194 -0
package/src/common.ts
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common logic for both Node.js and browser implementations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import ms = require('ms');
|
|
6
|
+
import {
|
|
7
|
+
Debugger,
|
|
8
|
+
DebugFactory,
|
|
9
|
+
DebugOptions,
|
|
10
|
+
EnvironmentConfig,
|
|
11
|
+
FilterOptions,
|
|
12
|
+
} from './types';
|
|
13
|
+
import { FilterManager, globalFilter } from './filter';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Setup function that creates the debug factory with environment-specific config
|
|
17
|
+
*/
|
|
18
|
+
export function setup(env: EnvironmentConfig): DebugFactory {
|
|
19
|
+
/**
|
|
20
|
+
* Create a new debugger instance
|
|
21
|
+
*/
|
|
22
|
+
function createDebug(namespace: string, options: DebugOptions = {}): Debugger {
|
|
23
|
+
let prevTime: number | undefined;
|
|
24
|
+
let enableOverride: boolean | null = null;
|
|
25
|
+
let namespacesCache: string;
|
|
26
|
+
let enabledCache: boolean;
|
|
27
|
+
|
|
28
|
+
// Instance-specific filter
|
|
29
|
+
const instanceFilter = new FilterManager(options.filter);
|
|
30
|
+
|
|
31
|
+
function debug(...args: any[]): void {
|
|
32
|
+
// Check if disabled (using the property that will be defined below)
|
|
33
|
+
if (!(debug as any).enabled) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Apply global and instance filters
|
|
38
|
+
if (!globalFilter.shouldLog(namespace, args)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!instanceFilter.shouldLog(namespace, args)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const self = debug;
|
|
47
|
+
|
|
48
|
+
// Set timestamp diffs
|
|
49
|
+
const curr = Number(new Date());
|
|
50
|
+
const ms = curr - (prevTime || curr);
|
|
51
|
+
self.diff = ms;
|
|
52
|
+
self.prev = prevTime || curr;
|
|
53
|
+
self.curr = curr;
|
|
54
|
+
prevTime = curr;
|
|
55
|
+
|
|
56
|
+
args[0] = (createDebug as any).coerce(args[0]);
|
|
57
|
+
|
|
58
|
+
if (typeof args[0] !== 'string') {
|
|
59
|
+
// Inspect with %O
|
|
60
|
+
args.unshift('%O');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Apply formatters
|
|
64
|
+
let index = 0;
|
|
65
|
+
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match: string, format: string) => {
|
|
66
|
+
// Handle escaped %
|
|
67
|
+
if (match === '%%') {
|
|
68
|
+
return '%';
|
|
69
|
+
}
|
|
70
|
+
index++;
|
|
71
|
+
const formatter = (createDebug as any).formatters[format];
|
|
72
|
+
if (typeof formatter === 'function') {
|
|
73
|
+
const val = args[index];
|
|
74
|
+
match = formatter.call(self, val);
|
|
75
|
+
// Remove the inlined argument
|
|
76
|
+
args.splice(index, 1);
|
|
77
|
+
index--;
|
|
78
|
+
}
|
|
79
|
+
return match;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Apply environment-specific formatting
|
|
83
|
+
(createDebug as any).formatArgs.call(self, args);
|
|
84
|
+
|
|
85
|
+
const logFn = self.log || (createDebug as any).log;
|
|
86
|
+
logFn.apply(self, args);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
debug.namespace = namespace;
|
|
90
|
+
debug.useColors = options.useColors ?? (createDebug as any).useColors();
|
|
91
|
+
debug.color = options.color ?? (createDebug as any).selectColor(namespace);
|
|
92
|
+
debug.diff = 0;
|
|
93
|
+
debug.prev = 0;
|
|
94
|
+
debug.curr = 0;
|
|
95
|
+
debug.metadata = options.metadata || {};
|
|
96
|
+
debug.log = options.log || env.log;
|
|
97
|
+
|
|
98
|
+
debug.extend = function (ns: string, delimiter?: string): Debugger {
|
|
99
|
+
const sep = typeof delimiter === 'undefined' ? ':' : delimiter;
|
|
100
|
+
const newDebug = createDebug(this.namespace + sep + ns);
|
|
101
|
+
newDebug.log = this.log;
|
|
102
|
+
return newDebug;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
debug.destroy = (createDebug as any).destroy;
|
|
106
|
+
|
|
107
|
+
debug.setFilter = function (filter: FilterOptions) {
|
|
108
|
+
instanceFilter.setOptions(filter);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
debug.setMetadata = function (key: string, value: any) {
|
|
112
|
+
this.metadata[key] = value;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
debug.getMetadata = function (key: string) {
|
|
116
|
+
return this.metadata[key];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
Object.defineProperty(debug, 'enabled', {
|
|
120
|
+
enumerable: true,
|
|
121
|
+
configurable: false,
|
|
122
|
+
get(): boolean {
|
|
123
|
+
if (enableOverride !== null) {
|
|
124
|
+
return enableOverride;
|
|
125
|
+
}
|
|
126
|
+
if (namespacesCache !== (createDebug as any).namespaces) {
|
|
127
|
+
namespacesCache = (createDebug as any).namespaces;
|
|
128
|
+
enabledCache = (createDebug as any).enabled(namespace);
|
|
129
|
+
}
|
|
130
|
+
return enabledCache;
|
|
131
|
+
},
|
|
132
|
+
set(v: boolean) {
|
|
133
|
+
enableOverride = v;
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Environment-specific initialization
|
|
138
|
+
if (typeof (createDebug as any).init === 'function') {
|
|
139
|
+
(createDebug as any).init(debug);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return debug as Debugger;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Attach properties from environment config
|
|
146
|
+
(createDebug as any).names = [];
|
|
147
|
+
(createDebug as any).skips = [];
|
|
148
|
+
(createDebug as any).formatters = {};
|
|
149
|
+
(createDebug as any).namespaces = '';
|
|
150
|
+
|
|
151
|
+
// Copy environment-specific properties
|
|
152
|
+
Object.keys(env).forEach((key) => {
|
|
153
|
+
(createDebug as any)[key] = (env as any)[key];
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
createDebug.humanize = ms;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Select a color for a namespace
|
|
160
|
+
*/
|
|
161
|
+
(createDebug as any).selectColor = function (namespace: string): string | number {
|
|
162
|
+
let hash = 0;
|
|
163
|
+
for (let i = 0; i < namespace.length; i++) {
|
|
164
|
+
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
165
|
+
hash |= 0; // Convert to 32bit integer
|
|
166
|
+
}
|
|
167
|
+
return (createDebug as any).colors[Math.abs(hash) % (createDebug as any).colors.length];
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Enable namespaces
|
|
172
|
+
*/
|
|
173
|
+
(createDebug as any).enable = function (namespaces: string): void {
|
|
174
|
+
(createDebug as any).save(namespaces);
|
|
175
|
+
(createDebug as any).namespaces = namespaces;
|
|
176
|
+
|
|
177
|
+
(createDebug as any).names = [];
|
|
178
|
+
(createDebug as any).skips = [];
|
|
179
|
+
|
|
180
|
+
const split = (typeof namespaces === 'string' ? namespaces : '')
|
|
181
|
+
.trim()
|
|
182
|
+
.replace(/\s+/g, ',')
|
|
183
|
+
.split(',')
|
|
184
|
+
.filter(Boolean);
|
|
185
|
+
|
|
186
|
+
for (const ns of split) {
|
|
187
|
+
if (ns[0] === '-') {
|
|
188
|
+
(createDebug as any).skips.push(ns.slice(1));
|
|
189
|
+
} else {
|
|
190
|
+
(createDebug as any).names.push(ns);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Disable all namespaces
|
|
197
|
+
*/
|
|
198
|
+
(createDebug as any).disable = function (): string {
|
|
199
|
+
const namespaces = [
|
|
200
|
+
...(createDebug as any).names,
|
|
201
|
+
...(createDebug as any).skips.map((ns: string) => '-' + ns),
|
|
202
|
+
].join(',');
|
|
203
|
+
(createDebug as any).enable('');
|
|
204
|
+
return namespaces;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Check if a namespace is enabled
|
|
209
|
+
*/
|
|
210
|
+
(createDebug as any).enabled = function (name: string): boolean {
|
|
211
|
+
// Check skips first
|
|
212
|
+
for (const skip of (createDebug as any).skips) {
|
|
213
|
+
if (matchesTemplate(name, skip)) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check names
|
|
219
|
+
for (const ns of (createDebug as any).names) {
|
|
220
|
+
if (matchesTemplate(name, ns)) {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return false;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Coerce a value
|
|
230
|
+
*/
|
|
231
|
+
(createDebug as any).coerce = function (val: any): any {
|
|
232
|
+
if (val instanceof Error) {
|
|
233
|
+
return val.stack || val.message;
|
|
234
|
+
}
|
|
235
|
+
return val;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Destroy (deprecated)
|
|
240
|
+
*/
|
|
241
|
+
(createDebug as any).destroy = function (): void {
|
|
242
|
+
console.warn(
|
|
243
|
+
'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version.'
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Set global filter options
|
|
249
|
+
*/
|
|
250
|
+
(createDebug as any).setGlobalFilter = function (filter: FilterOptions) {
|
|
251
|
+
globalFilter.setOptions(filter);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get global filter options
|
|
256
|
+
*/
|
|
257
|
+
(createDebug as any).getGlobalFilter = function () {
|
|
258
|
+
return globalFilter.getOptions();
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// Load saved namespaces
|
|
262
|
+
(createDebug as any).enable((createDebug as any).load());
|
|
263
|
+
|
|
264
|
+
return createDebug as any as DebugFactory;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Match a namespace against a template with wildcards
|
|
269
|
+
*/
|
|
270
|
+
function matchesTemplate(search: string, template: string): boolean {
|
|
271
|
+
let searchIndex = 0;
|
|
272
|
+
let templateIndex = 0;
|
|
273
|
+
let starIndex = -1;
|
|
274
|
+
let matchIndex = 0;
|
|
275
|
+
|
|
276
|
+
while (searchIndex < search.length) {
|
|
277
|
+
if (
|
|
278
|
+
templateIndex < template.length &&
|
|
279
|
+
(template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')
|
|
280
|
+
) {
|
|
281
|
+
if (template[templateIndex] === '*') {
|
|
282
|
+
starIndex = templateIndex;
|
|
283
|
+
matchIndex = searchIndex;
|
|
284
|
+
templateIndex++;
|
|
285
|
+
} else {
|
|
286
|
+
searchIndex++;
|
|
287
|
+
templateIndex++;
|
|
288
|
+
}
|
|
289
|
+
} else if (starIndex !== -1) {
|
|
290
|
+
templateIndex = starIndex + 1;
|
|
291
|
+
matchIndex++;
|
|
292
|
+
searchIndex = matchIndex;
|
|
293
|
+
} else {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Handle trailing wildcards
|
|
299
|
+
while (templateIndex < template.length && template[templateIndex] === '*') {
|
|
300
|
+
templateIndex++;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return templateIndex === template.length;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export { matchesTemplate };
|
package/src/filter.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advanced filtering capabilities for debug-utility
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { FilterOptions, FilterPredicate } from './types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Filter manager class for handling complex filtering logic
|
|
9
|
+
*/
|
|
10
|
+
export class FilterManager {
|
|
11
|
+
private options: FilterOptions;
|
|
12
|
+
|
|
13
|
+
constructor(options: FilterOptions = {}) {
|
|
14
|
+
this.options = {
|
|
15
|
+
enabled: true,
|
|
16
|
+
patterns: [],
|
|
17
|
+
predicates: [],
|
|
18
|
+
tags: [],
|
|
19
|
+
include: [],
|
|
20
|
+
exclude: [],
|
|
21
|
+
...options,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Update filter options
|
|
27
|
+
*/
|
|
28
|
+
setOptions(options: Partial<FilterOptions>): void {
|
|
29
|
+
this.options = { ...this.options, ...options };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get current filter options
|
|
34
|
+
*/
|
|
35
|
+
getOptions(): FilterOptions {
|
|
36
|
+
return { ...this.options };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if a namespace passes the filter
|
|
41
|
+
*/
|
|
42
|
+
shouldLog(namespace: string, args: any[] = []): boolean {
|
|
43
|
+
if (!this.options.enabled) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check exclude list first (highest priority)
|
|
48
|
+
if (this.options.exclude && this.options.exclude.length > 0) {
|
|
49
|
+
for (const pattern of this.options.exclude) {
|
|
50
|
+
if (this.matchPattern(namespace, pattern)) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check include list
|
|
57
|
+
if (this.options.include && this.options.include.length > 0) {
|
|
58
|
+
let included = false;
|
|
59
|
+
for (const pattern of this.options.include) {
|
|
60
|
+
if (this.matchPattern(namespace, pattern)) {
|
|
61
|
+
included = true;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!included) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check regex patterns
|
|
71
|
+
if (this.options.patterns && this.options.patterns.length > 0) {
|
|
72
|
+
let matched = false;
|
|
73
|
+
for (const pattern of this.options.patterns) {
|
|
74
|
+
if (pattern.test(namespace)) {
|
|
75
|
+
matched = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!matched) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check custom predicates
|
|
85
|
+
if (this.options.predicates && this.options.predicates.length > 0) {
|
|
86
|
+
for (const predicate of this.options.predicates) {
|
|
87
|
+
if (!predicate(namespace, ...args)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check tags (if first argument is an object with tags)
|
|
94
|
+
if (this.options.tags && this.options.tags.length > 0) {
|
|
95
|
+
if (args.length > 0 && typeof args[0] === 'object' && args[0].tags) {
|
|
96
|
+
const argTags = Array.isArray(args[0].tags) ? args[0].tags : [args[0].tags];
|
|
97
|
+
const hasMatchingTag = argTags.some((tag: string) =>
|
|
98
|
+
this.options.tags!.includes(tag)
|
|
99
|
+
);
|
|
100
|
+
if (!hasMatchingTag) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Match a namespace against a pattern (supports wildcards)
|
|
111
|
+
*/
|
|
112
|
+
private matchPattern(namespace: string, pattern: string): boolean {
|
|
113
|
+
// Convert wildcard pattern to regex
|
|
114
|
+
const regexPattern = pattern
|
|
115
|
+
.replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape special chars
|
|
116
|
+
.replace(/\*/g, '.*'); // Replace * with .*
|
|
117
|
+
|
|
118
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
119
|
+
return regex.test(namespace);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Add a custom predicate filter
|
|
124
|
+
*/
|
|
125
|
+
addPredicate(predicate: FilterPredicate): void {
|
|
126
|
+
if (!this.options.predicates) {
|
|
127
|
+
this.options.predicates = [];
|
|
128
|
+
}
|
|
129
|
+
this.options.predicates.push(predicate);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Add a regex pattern filter
|
|
134
|
+
*/
|
|
135
|
+
addPattern(pattern: RegExp): void {
|
|
136
|
+
if (!this.options.patterns) {
|
|
137
|
+
this.options.patterns = [];
|
|
138
|
+
}
|
|
139
|
+
this.options.patterns.push(pattern);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Add include pattern
|
|
144
|
+
*/
|
|
145
|
+
addInclude(pattern: string): void {
|
|
146
|
+
if (!this.options.include) {
|
|
147
|
+
this.options.include = [];
|
|
148
|
+
}
|
|
149
|
+
this.options.include.push(pattern);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Add exclude pattern
|
|
154
|
+
*/
|
|
155
|
+
addExclude(pattern: string): void {
|
|
156
|
+
if (!this.options.exclude) {
|
|
157
|
+
this.options.exclude = [];
|
|
158
|
+
}
|
|
159
|
+
this.options.exclude.push(pattern);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Add tag filter
|
|
164
|
+
*/
|
|
165
|
+
addTag(tag: string): void {
|
|
166
|
+
if (!this.options.tags) {
|
|
167
|
+
this.options.tags = [];
|
|
168
|
+
}
|
|
169
|
+
this.options.tags.push(tag);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Clear all filters
|
|
174
|
+
*/
|
|
175
|
+
clear(): void {
|
|
176
|
+
this.options = {
|
|
177
|
+
enabled: true,
|
|
178
|
+
patterns: [],
|
|
179
|
+
predicates: [],
|
|
180
|
+
tags: [],
|
|
181
|
+
include: [],
|
|
182
|
+
exclude: [],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Enable filtering
|
|
188
|
+
*/
|
|
189
|
+
enable(): void {
|
|
190
|
+
this.options.enabled = true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Disable filtering
|
|
195
|
+
*/
|
|
196
|
+
disable(): void {
|
|
197
|
+
this.options.enabled = false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Global filter instance
|
|
203
|
+
*/
|
|
204
|
+
export const globalFilter = new FilterManager();
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main entry point - detects environment and loads appropriate implementation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Detect Electron renderer / nwjs process, which is node, but should
|
|
7
|
+
* be treated as a browser.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
if (
|
|
11
|
+
typeof process === 'undefined' ||
|
|
12
|
+
(process as any).type === 'renderer' ||
|
|
13
|
+
(process as any).browser === true ||
|
|
14
|
+
(process as any).__nwjs
|
|
15
|
+
) {
|
|
16
|
+
module.exports = require('./browser');
|
|
17
|
+
} else {
|
|
18
|
+
module.exports = require('./node');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Export types for TypeScript users
|
|
22
|
+
export * from './types';
|
|
23
|
+
export { FilterManager, globalFilter } from './filter';
|
package/src/node.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js implementation of debug-utility
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as tty from 'tty';
|
|
6
|
+
import * as util from 'util';
|
|
7
|
+
import { setup } from './common';
|
|
8
|
+
import { EnvironmentConfig, Debugger } from './types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Colors for Node.js (ANSI color codes)
|
|
12
|
+
*/
|
|
13
|
+
const colors = [
|
|
14
|
+
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, 69, 74, 75, 76, 77,
|
|
15
|
+
78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, 135, 148, 149, 160, 161, 162, 163, 164,
|
|
16
|
+
165, 166, 167, 168, 169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201,
|
|
17
|
+
202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221,
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if supports-color is available (optional dependency)
|
|
22
|
+
*/
|
|
23
|
+
try {
|
|
24
|
+
const supportsColor = require('supports-color');
|
|
25
|
+
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
|
26
|
+
// Use extended color palette if available
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// supports-color is optional
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Build inspect options from environment variables
|
|
34
|
+
*/
|
|
35
|
+
const inspectOpts = Object.keys(process.env)
|
|
36
|
+
.filter((key) => /^debug_/i.test(key))
|
|
37
|
+
.reduce((obj: Record<string, any>, key: string) => {
|
|
38
|
+
// Convert DEBUG_COLORS to colors
|
|
39
|
+
const prop = key
|
|
40
|
+
.substring(6)
|
|
41
|
+
.toLowerCase()
|
|
42
|
+
.replace(/_([a-z])/g, (_, k) => k.toUpperCase());
|
|
43
|
+
|
|
44
|
+
// Coerce string value
|
|
45
|
+
let val: any = process.env[key];
|
|
46
|
+
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
|
47
|
+
val = true;
|
|
48
|
+
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
|
49
|
+
val = false;
|
|
50
|
+
} else if (val === 'null') {
|
|
51
|
+
val = null;
|
|
52
|
+
} else {
|
|
53
|
+
val = Number(val);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
obj[prop] = val;
|
|
57
|
+
return obj;
|
|
58
|
+
}, {});
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if colors should be used
|
|
62
|
+
*/
|
|
63
|
+
function useColors(): boolean {
|
|
64
|
+
if ('colors' in inspectOpts) {
|
|
65
|
+
return Boolean(inspectOpts.colors);
|
|
66
|
+
}
|
|
67
|
+
return tty.isatty(process.stderr.fd);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Format arguments with ANSI colors
|
|
72
|
+
*/
|
|
73
|
+
function formatArgs(this: Debugger, args: any[]): void {
|
|
74
|
+
const { namespace, useColors: shouldUseColors } = this;
|
|
75
|
+
|
|
76
|
+
if (shouldUseColors) {
|
|
77
|
+
const c = this.color as number;
|
|
78
|
+
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
|
|
79
|
+
const prefix = ` ${colorCode};1m${namespace} \u001B[0m`;
|
|
80
|
+
|
|
81
|
+
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
|
82
|
+
args.push(colorCode + 'm+' + ms(this.diff) + '\u001B[0m');
|
|
83
|
+
} else {
|
|
84
|
+
args[0] = getDate() + namespace + ' ' + args[0];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get formatted date
|
|
90
|
+
*/
|
|
91
|
+
function getDate(): string {
|
|
92
|
+
if (inspectOpts.hideDate) {
|
|
93
|
+
return '';
|
|
94
|
+
}
|
|
95
|
+
return new Date().toISOString() + ' ';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Log to stderr
|
|
100
|
+
*/
|
|
101
|
+
function log(...args: any[]): void {
|
|
102
|
+
process.stderr.write(util.formatWithOptions(inspectOpts, ...args) + '\n');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Save namespaces to environment
|
|
107
|
+
*/
|
|
108
|
+
function save(namespaces: string): void {
|
|
109
|
+
if (namespaces) {
|
|
110
|
+
process.env.DEBUG = namespaces;
|
|
111
|
+
} else {
|
|
112
|
+
delete process.env.DEBUG;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Load namespaces from environment
|
|
118
|
+
*/
|
|
119
|
+
function load(): string {
|
|
120
|
+
return process.env.DEBUG || '';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Destroy function (deprecated)
|
|
125
|
+
*/
|
|
126
|
+
function destroy(): void {
|
|
127
|
+
console.warn(
|
|
128
|
+
'Instance method `debug.destroy()` is deprecated and no longer does anything.'
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Initialize a debug instance (optional)
|
|
134
|
+
*/
|
|
135
|
+
function init(debug: Debugger): void {
|
|
136
|
+
// Initialization logic can be added here if needed
|
|
137
|
+
(debug as any).inspectOpts = inspectOpts;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Import ms for humanizing time
|
|
141
|
+
import ms = require('ms');
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Create environment config for Node.js
|
|
145
|
+
*/
|
|
146
|
+
const nodeEnv: EnvironmentConfig = {
|
|
147
|
+
formatArgs,
|
|
148
|
+
save,
|
|
149
|
+
load,
|
|
150
|
+
useColors,
|
|
151
|
+
colors,
|
|
152
|
+
log,
|
|
153
|
+
inspectOpts,
|
|
154
|
+
init,
|
|
155
|
+
destroy,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Export the debug factory
|
|
160
|
+
*/
|
|
161
|
+
export = setup(nodeEnv);
|