@leftium/gg 0.0.33 → 0.0.35

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 CHANGED
@@ -18,24 +18,101 @@
18
18
  npm add @leftium/gg
19
19
  ```
20
20
 
21
- ## Usage
21
+ ## SvelteKit Quick Start
22
22
 
23
- ### Basic Logging
23
+ ### 1. Use `gg()` anywhere
24
24
 
25
- ```javascript
26
- import { gg } from '@leftium/gg';
25
+ ```svelte
26
+ <script>
27
+ import { gg } from '@leftium/gg';
28
+
29
+ gg('Hello world');
30
+
31
+ // Log expressions (returns first argument)
32
+ const result = gg(someFunction());
33
+
34
+ // Multiple arguments
35
+ gg('User:', user, 'Status:', status);
36
+ </script>
37
+ ```
38
+
39
+ That's it! Output appears in the browser dev console and terminal. The following optional steps are highly recommended to unlock the full experience:
40
+
41
+ ### 2. Add Vite plugins (optional, recommended)
42
+
43
+ Without plugins, namespaces are random word-tuples. With plugins, you get real file/function callpoints, open-in-editor links, and icecream-style source expressions.
44
+
45
+ ```ts
46
+ // vite.config.ts
47
+ import ggPlugins from '@leftium/gg/vite';
48
+ import { sveltekit } from '@sveltejs/kit/vite';
49
+ import { defineConfig } from 'vite';
50
+
51
+ export default defineConfig({
52
+ plugins: [sveltekit(), ...ggPlugins()]
53
+ });
54
+ ```
55
+
56
+ `ggPlugins()` includes:
57
+
58
+ - **Call-sites plugin** -- rewrites `gg()` calls with source file/line/col metadata
59
+ - **Open-in-editor plugin** -- adds dev server middleware for click-to-open
60
+ - **Automatic `es2022` target** -- required for top-level await
61
+
62
+ ### 3. Add the debug console (optional, recommended)
63
+
64
+ An in-browser debug console (powered by Eruda) with a dedicated GG tab for filtering and inspecting logs — especially useful on mobile.
65
+
66
+ ```svelte
67
+ <!-- src/routes/+layout.svelte -->
68
+ <script>
69
+ import { GgConsole } from '@leftium/gg';
70
+ </script>
71
+
72
+ <GgConsole />
73
+ {@render children()}
74
+ ```
75
+
76
+ In development, the debug console appears automatically.
77
+ In production, add `?gg` to the URL or use a 5-tap gesture to activate.
27
78
 
28
- // Simple logging
29
- gg('Hello world');
79
+ ## GgConsole Options
30
80
 
31
- // Log expressions (returns first argument)
32
- const result = gg(someFunction());
81
+ ```svelte
82
+ <GgConsole prod={['url-param', 'gesture']} maxEntries={5000} />
83
+ ```
84
+
85
+ | Prop | Type | Default | Description |
86
+ | -------------- | -------------------------- | -------------------------- | ------------------------------ |
87
+ | `prod` | `Array \| string \| false` | `['url-param', 'gesture']` | Production activation triggers |
88
+ | `maxEntries` | `number` | `2000` | Max log entries in ring buffer |
89
+ | `erudaOptions` | `object` | `{}` | Pass-through options to Eruda |
90
+
91
+ **Production triggers:**
92
+
93
+ - `'url-param'` -- activate with `?gg` in the URL (persists to localStorage)
94
+ - `'gesture'` -- activate with 5 rapid taps anywhere on the page
95
+ - `'localStorage'` -- activate if `localStorage['gg-enabled']` is `'true'`
96
+ - `false` -- disable debug console in production entirely
97
+
98
+ ## Vite Plugin Options
33
99
 
34
- // Multiple arguments
35
- gg('User:', user, 'Status:', status);
100
+ ```ts
101
+ import ggPlugins from '@leftium/gg/vite';
102
+
103
+ ggPlugins({
104
+ callSites: { srcRootPattern: '.*?(/src/)' },
105
+ openInEditor: false // disable open-in-editor middleware
106
+ });
36
107
  ```
37
108
 
38
- ### Color Support (ANSI)
109
+ Individual plugins are also available for advanced setups:
110
+
111
+ ```ts
112
+ import { ggCallSitesPlugin, openInEditorPlugin } from '@leftium/gg/vite';
113
+ ```
114
+
115
+ ## Color Support (ANSI)
39
116
 
40
117
  Color your logs for better visual distinction using `fg()` (foreground/text) and `bg()` (background):
41
118
 
@@ -77,46 +154,56 @@ gg(fg('rgb(255,99,71)')`Tomato text`);
77
154
 
78
155
  **Where colors work:**
79
156
 
80
- - Native browser console (Chrome DevTools, Firefox, etc.)
81
- - Eruda GG panel (mobile debugging)
82
- - Node.js terminal
83
- - All environments that support ANSI escape codes
157
+ - Native browser console (Chrome DevTools, Firefox, etc.)
158
+ - GgConsole debug panel (mobile debugging)
159
+ - Node.js terminal
160
+ - All environments that support ANSI escape codes
84
161
 
85
- ## Technical Details
162
+ ## Other Frameworks
86
163
 
87
- ### Bundled Dependencies
164
+ `gg()` works in any JavaScript project. The Vite plugins work with any Vite-based framework (React, Vue, Solid, etc.).
88
165
 
89
- This library includes a **patched version** of the [`debug`](https://www.npmjs.com/package/debug) package. The patch reformats the output to display time diffs **before** the namespace for better readability:
166
+ ### Vanilla / Non-Svelte Setup
90
167
 
91
- **Standard debug output:**
168
+ ```ts
169
+ // vite.config.ts
170
+ import ggPlugins from '@leftium/gg/vite';
92
171
 
93
- ```
94
- gg:routes/+page.svelte +123ms
172
+ export default defineConfig({
173
+ plugins: [...ggPlugins()]
174
+ });
95
175
  ```
96
176
 
97
- **Patched output (this library):**
177
+ ```js
178
+ // app.js
179
+ import { gg } from '@leftium/gg';
180
+ import { initGgEruda } from '@leftium/gg/eruda';
98
181
 
182
+ initGgEruda();
183
+ gg('works in any framework');
99
184
  ```
100
- +123ms gg:routes/+page.svelte
101
- ```
102
185
 
103
- The patched `debug` library is bundled directly into the distribution, so consumers automatically get the correct behavior without needing to install or patch `debug` themselves.
186
+ ## Technical Details
187
+
188
+ ### Internal Debug Implementation
189
+
190
+ This library includes an **internal TypeScript implementation** inspired by the [`debug`](https://www.npmjs.com/package/debug) package. The output format displays time diffs **before** the namespace for better readability:
104
191
 
105
- ### Updating the Bundled debug Library
192
+ **Output format:**
106
193
 
107
- When a new version of `debug` is released:
194
+ ```
195
+ +123ms gg:routes/+page.svelte
196
+ ```
108
197
 
109
- 1. Update debug: `pnpm add debug@x.x.x`
110
- 2. Update patch: `pnpm patch debug@x.x.x` (apply changes, then `pnpm patch-commit`)
111
- 3. Run the update script: `./scripts/update-debug.sh`
112
- 4. Verify patches are present: `git diff src/lib/debug/src/`
113
- 5. Test dev mode: `pnpm dev`
114
- 6. Test production build: `pnpm prepack`
115
- 7. Commit changes: `git commit -am "Update bundled debug to x.x.x"`
198
+ Features implemented internally (~290 lines of TypeScript):
116
199
 
117
- The patch is maintained in `patches/debug@4.4.3.patch` for reference.
200
+ - Color hashing algorithm for consistent namespace colors
201
+ - Millisecond diff formatting (e.g., `+123ms`, `+2s`, `+5m`)
202
+ - Namespace wildcard matching (`gg:*`, `gg:routes/*`, `-gg:test`)
203
+ - localStorage.debug / process.env.DEBUG persistence
204
+ - Browser and Node.js environments
118
205
 
119
- **Note:** `debug` is kept in dependencies (not devDependencies) to support both dev and production modes.
206
+ This approach eliminates the need for vendoring, patching, and bundling third-party code, resulting in better type safety and simpler maintenance.
120
207
 
121
208
  ## Inspirations
122
209
 
@@ -0,0 +1,12 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import type { GgErudaOptions } from './eruda/types.js';
4
+
5
+ let { prod, maxEntries, erudaOptions }: GgErudaOptions = $props();
6
+
7
+ onMount(() => {
8
+ import('./eruda/index.js').then(({ initGgEruda }) => {
9
+ initGgEruda({ prod, maxEntries, erudaOptions });
10
+ });
11
+ });
12
+ </script>
@@ -0,0 +1,4 @@
1
+ import type { GgErudaOptions } from './eruda/types.js';
2
+ declare const GgConsole: import("svelte").Component<GgErudaOptions, {}, "">;
3
+ type GgConsole = ReturnType<typeof GgConsole>;
4
+ export default GgConsole;
@@ -1,22 +1,32 @@
1
1
  <script lang="ts">
2
2
  import { dev } from '$app/environment';
3
3
 
4
+ type GgCallSiteInfo = { fileName: string; functionName: string; url: string };
5
+
4
6
  let {
5
- url,
6
- fileName,
7
- title = fileName
8
- }: { url: string; fileName: string; title?: string } = $props();
7
+ gg,
8
+ url = gg?.url,
9
+ fileName = gg?.fileName,
10
+ title = gg ? `${gg.fileName}@${gg.functionName}` : fileName
11
+ }: {
12
+ gg?: GgCallSiteInfo;
13
+ url?: string;
14
+ fileName?: string;
15
+ title?: string;
16
+ } = $props();
9
17
 
10
18
  // svelte-ignore non_reactive_update
11
19
  let iframeElement: HTMLIFrameElement;
12
20
 
13
21
  function onclick(event: MouseEvent) {
14
- iframeElement.src = url;
15
- event.preventDefault();
22
+ if (url) {
23
+ iframeElement.src = url;
24
+ event.preventDefault();
25
+ }
16
26
  }
17
27
  </script>
18
28
 
19
- {#if dev}
29
+ {#if dev && fileName}
20
30
  [📝<a {onclick} href={url} {title} target="_open-in-editor" class="open-in-editor-link">
21
31
  {fileName}
22
32
  </a>
@@ -1,6 +1,12 @@
1
- type $$ComponentProps = {
2
- url: string;
1
+ type GgCallSiteInfo = {
3
2
  fileName: string;
3
+ functionName: string;
4
+ url: string;
5
+ };
6
+ type $$ComponentProps = {
7
+ gg?: GgCallSiteInfo;
8
+ url?: string;
9
+ fileName?: string;
4
10
  title?: string;
5
11
  };
6
12
  declare const OpenInEditorLink: import("svelte").Component<$$ComponentProps, {}, "">;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Browser-specific debug implementation.
3
+ *
4
+ * Output: console.debug with %c CSS color formatting.
5
+ * Persistence: localStorage.debug
6
+ * Format (patched): +123ms namespace message
7
+ */
8
+ import { type DebugFactory } from './common.js';
9
+ declare const debug: DebugFactory;
10
+ export default debug;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Browser-specific debug implementation.
3
+ *
4
+ * Output: console.debug with %c CSS color formatting.
5
+ * Persistence: localStorage.debug
6
+ * Format (patched): +123ms namespace message
7
+ */
8
+ import { setup, humanize } from './common.js';
9
+ /**
10
+ * 76 hex colors — identical to debug@4 browser.js for color-hash stability.
11
+ */
12
+ const colors = [
13
+ '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF',
14
+ '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99',
15
+ '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF',
16
+ '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33',
17
+ '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF',
18
+ '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF',
19
+ '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033',
20
+ '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333',
21
+ '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633',
22
+ '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033',
23
+ '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333',
24
+ '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633',
25
+ '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'
26
+ ];
27
+ function useColors() {
28
+ // Modern browsers all support %c — simplified from debug's original checks
29
+ return typeof document !== 'undefined' || typeof navigator !== 'undefined';
30
+ }
31
+ /**
32
+ * Format args with color CSS and gg's patched prefix order:
33
+ * +123ms namespace message
34
+ */
35
+ function formatArgs(args) {
36
+ const h = humanize(this.diff);
37
+ const prefix = ('+' + h).padStart(6);
38
+ args[0] = (this.useColors ? '%c' : '') +
39
+ `${prefix} ${this.namespace}` +
40
+ (this.useColors ? ' %c' : ' ') +
41
+ args[0] +
42
+ (this.useColors ? '%c ' : ' ');
43
+ if (!this.useColors)
44
+ return;
45
+ const c = 'color: ' + this.color;
46
+ args.splice(1, 0, c, 'color: inherit');
47
+ // Insert CSS for the final %c
48
+ let index = 0;
49
+ let lastC = 0;
50
+ args[0].replace(/%[a-zA-Z%]/g, (match) => {
51
+ if (match === '%%')
52
+ return match;
53
+ index++;
54
+ if (match === '%c')
55
+ lastC = index;
56
+ return match;
57
+ });
58
+ args.splice(lastC, 0, c);
59
+ }
60
+ function save(namespaces) {
61
+ try {
62
+ if (namespaces) {
63
+ localStorage.setItem('debug', namespaces);
64
+ }
65
+ else {
66
+ localStorage.removeItem('debug');
67
+ }
68
+ }
69
+ catch {
70
+ // localStorage may not be available
71
+ }
72
+ }
73
+ function load() {
74
+ try {
75
+ return localStorage.getItem('debug') || localStorage.getItem('DEBUG') || '';
76
+ }
77
+ catch {
78
+ return '';
79
+ }
80
+ }
81
+ const log = console.debug || console.log || (() => { });
82
+ const env = {
83
+ formatArgs,
84
+ save,
85
+ load,
86
+ useColors,
87
+ colors,
88
+ log,
89
+ formatters: {
90
+ /** %j → JSON.stringify (preserved for compatibility) */
91
+ j(v) {
92
+ try {
93
+ return JSON.stringify(v);
94
+ }
95
+ catch (e) {
96
+ return '[UnexpectedJSONParseError]: ' + e.message;
97
+ }
98
+ }
99
+ }
100
+ };
101
+ const debug = setup(env);
102
+ export default debug;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Internal debug implementation — replaces the `debug` npm package.
3
+ *
4
+ * Core logic: createDebug factory, enable/disable, namespace matching,
5
+ * color selection, and humanize (ms formatting).
6
+ */
7
+ /** Format ms like debug's `ms` package: 0ms, 500ms, 5s, 2m, 1h, 3d */
8
+ export declare function humanize(ms: number): string;
9
+ export interface Debugger {
10
+ (...args: unknown[]): void;
11
+ namespace: string;
12
+ color: string;
13
+ diff: number;
14
+ enabled: boolean;
15
+ useColors: boolean;
16
+ formatArgs: (args: unknown[]) => void;
17
+ log: ((...args: unknown[]) => void) | null;
18
+ }
19
+ export interface DebugFactory {
20
+ (namespace: string): Debugger;
21
+ enable: (namespaces: string) => void;
22
+ disable: () => string;
23
+ enabled: (namespace: string) => boolean;
24
+ humanize: typeof humanize;
25
+ names: string[];
26
+ skips: string[];
27
+ namespaces: string;
28
+ formatters: Record<string, (this: Debugger, val: unknown) => string>;
29
+ }
30
+ /** Platform-specific hooks provided by browser.ts or node.ts */
31
+ export interface DebugEnv {
32
+ formatArgs: (this: Debugger, args: unknown[]) => void;
33
+ save: (namespaces: string) => void;
34
+ load: () => string;
35
+ useColors: () => boolean;
36
+ colors: string[] | number[];
37
+ log: (...args: unknown[]) => void;
38
+ formatters?: Record<string, (this: Debugger, val: unknown) => string>;
39
+ init?: (instance: Debugger) => void;
40
+ }
41
+ export declare function setup(env: DebugEnv): DebugFactory;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Internal debug implementation — replaces the `debug` npm package.
3
+ *
4
+ * Core logic: createDebug factory, enable/disable, namespace matching,
5
+ * color selection, and humanize (ms formatting).
6
+ */
7
+ /** Format ms like debug's `ms` package: 0ms, 500ms, 5s, 2m, 1h, 3d */
8
+ export function humanize(ms) {
9
+ const abs = Math.abs(ms);
10
+ if (abs >= 86_400_000)
11
+ return Math.round(ms / 86_400_000) + 'd';
12
+ if (abs >= 3_600_000)
13
+ return Math.round(ms / 3_600_000) + 'h';
14
+ if (abs >= 60_000)
15
+ return Math.round(ms / 60_000) + 'm';
16
+ if (abs >= 1_000)
17
+ return Math.round(ms / 1_000) + 's';
18
+ return ms + 'ms';
19
+ }
20
+ /**
21
+ * Wildcard pattern matching (same algorithm as debug's `matchesTemplate`).
22
+ * Supports `*` as a wildcard that matches any sequence of characters.
23
+ */
24
+ function matchesTemplate(search, template) {
25
+ let si = 0;
26
+ let ti = 0;
27
+ let starIdx = -1;
28
+ let matchIdx = 0;
29
+ while (si < search.length) {
30
+ if (ti < template.length && (template[ti] === search[si] || template[ti] === '*')) {
31
+ if (template[ti] === '*') {
32
+ starIdx = ti;
33
+ matchIdx = si;
34
+ ti++;
35
+ }
36
+ else {
37
+ si++;
38
+ ti++;
39
+ }
40
+ }
41
+ else if (starIdx !== -1) {
42
+ ti = starIdx + 1;
43
+ matchIdx++;
44
+ si = matchIdx;
45
+ }
46
+ else {
47
+ return false;
48
+ }
49
+ }
50
+ while (ti < template.length && template[ti] === '*') {
51
+ ti++;
52
+ }
53
+ return ti === template.length;
54
+ }
55
+ // ── Factory ────────────────────────────────────────────────────────────
56
+ export function setup(env) {
57
+ /** Deterministic color for a namespace (same hash as debug@4) */
58
+ function selectColor(namespace) {
59
+ let hash = 0;
60
+ for (let i = 0; i < namespace.length; i++) {
61
+ hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
62
+ hash |= 0;
63
+ }
64
+ return env.colors[Math.abs(hash) % env.colors.length];
65
+ }
66
+ // Active include/exclude lists
67
+ let names = [];
68
+ let skips = [];
69
+ let currentNamespaces = '';
70
+ function enable(namespaces) {
71
+ env.save(namespaces);
72
+ currentNamespaces = namespaces;
73
+ names = [];
74
+ skips = [];
75
+ const parts = (typeof namespaces === 'string' ? namespaces : '')
76
+ .trim()
77
+ .replace(/\s+/g, ',')
78
+ .split(',')
79
+ .filter(Boolean);
80
+ for (const part of parts) {
81
+ if (part[0] === '-') {
82
+ skips.push(part.slice(1));
83
+ }
84
+ else {
85
+ names.push(part);
86
+ }
87
+ }
88
+ // Update factory-level arrays for external inspection
89
+ factory.names = names;
90
+ factory.skips = skips;
91
+ factory.namespaces = currentNamespaces;
92
+ }
93
+ function disable() {
94
+ const prev = [
95
+ ...names,
96
+ ...skips.map((ns) => '-' + ns)
97
+ ].join(',');
98
+ enable('');
99
+ return prev;
100
+ }
101
+ function enabled(name) {
102
+ for (const skip of skips) {
103
+ if (matchesTemplate(name, skip))
104
+ return false;
105
+ }
106
+ for (const ns of names) {
107
+ if (matchesTemplate(name, ns))
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+ // ── createDebug ────────────────────────────────────────────────────
113
+ function createDebug(namespace) {
114
+ let prevTime;
115
+ let enableOverride = null;
116
+ let namespacesCache;
117
+ let enabledCache;
118
+ const debug = function (...args) {
119
+ if (!debug.enabled)
120
+ return;
121
+ const curr = Date.now();
122
+ const ms = curr - (prevTime || curr);
123
+ debug.diff = ms;
124
+ prevTime = curr;
125
+ // Coerce first arg
126
+ if (typeof args[0] !== 'string') {
127
+ args.unshift('%O');
128
+ }
129
+ // Apply %format replacements
130
+ let idx = 0;
131
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, fmt) => {
132
+ if (match === '%%')
133
+ return '%';
134
+ idx++;
135
+ const formatter = factory.formatters[fmt];
136
+ if (typeof formatter === 'function') {
137
+ const val = args[idx];
138
+ match = formatter.call(debug, val);
139
+ args.splice(idx, 1);
140
+ idx--;
141
+ }
142
+ return match;
143
+ });
144
+ // Platform-specific formatting (colors, prefix)
145
+ debug.formatArgs(args);
146
+ const logFn = debug.log || env.log;
147
+ logFn.apply(debug, args);
148
+ };
149
+ debug.namespace = namespace;
150
+ debug.useColors = env.useColors();
151
+ debug.color = String(selectColor(namespace));
152
+ debug.diff = 0;
153
+ debug.log = null;
154
+ debug.formatArgs = function (args) {
155
+ env.formatArgs.call(debug, args);
156
+ };
157
+ Object.defineProperty(debug, 'enabled', {
158
+ enumerable: true,
159
+ configurable: false,
160
+ get: () => {
161
+ if (enableOverride !== null)
162
+ return enableOverride;
163
+ if (namespacesCache !== currentNamespaces) {
164
+ namespacesCache = currentNamespaces;
165
+ enabledCache = enabled(namespace);
166
+ }
167
+ return enabledCache;
168
+ },
169
+ set: (v) => {
170
+ enableOverride = v;
171
+ }
172
+ });
173
+ if (env.init) {
174
+ env.init(debug);
175
+ }
176
+ return debug;
177
+ }
178
+ // ── Assemble factory ───────────────────────────────────────────────
179
+ const factory = createDebug;
180
+ factory.enable = enable;
181
+ factory.disable = disable;
182
+ factory.enabled = enabled;
183
+ factory.humanize = humanize;
184
+ factory.names = names;
185
+ factory.skips = skips;
186
+ factory.namespaces = '';
187
+ factory.formatters = { ...env.formatters };
188
+ // Initialize from persisted namespaces
189
+ enable(env.load());
190
+ return factory;
191
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Debug entry point — selects browser or node implementation.
3
+ *
4
+ * Re-exports the DebugFactory and Debugger types for consumers.
5
+ */
6
+ import type { DebugFactory } from './common.js';
7
+ export type { DebugFactory, Debugger } from './common.js';
8
+ declare const _default: DebugFactory;
9
+ export default _default;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Debug entry point — selects browser or node implementation.
3
+ *
4
+ * Re-exports the DebugFactory and Debugger types for consumers.
5
+ */
6
+ import { BROWSER } from 'esm-env';
7
+ // Conditional import: browser.ts for browsers, node.ts for Node/Deno/Bun
8
+ const { default: debug } = BROWSER
9
+ ? await import('./browser.js')
10
+ : await import('./node.js');
11
+ export default debug;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Node.js-specific debug implementation.
3
+ *
4
+ * Output: process.stderr via util.formatWithOptions.
5
+ * Persistence: process.env.DEBUG
6
+ * Format (patched): +123ms namespace message (ANSI colored)
7
+ */
8
+ import { type DebugFactory } from './common.js';
9
+ declare const debug: DebugFactory;
10
+ export default debug;