@leftium/gg 0.0.31 → 0.0.34
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 +117 -36
- package/dist/GgConsole.svelte +12 -0
- package/dist/GgConsole.svelte.d.ts +4 -0
- package/dist/OpenInEditorLink.svelte +8 -10
- package/dist/OpenInEditorLink.svelte.d.ts +6 -3
- package/dist/debug/browser.d.ts +10 -0
- package/dist/debug/browser.js +102 -0
- package/dist/debug/common.d.ts +41 -0
- package/dist/debug/common.js +191 -0
- package/dist/debug/index.d.ts +9 -0
- package/dist/debug/index.js +11 -0
- package/dist/debug/node.d.ts +10 -0
- package/dist/debug/node.js +137 -0
- package/dist/eruda/loader.js +0 -11
- package/dist/eruda/plugin.js +765 -25
- package/dist/eruda/types.d.ts +8 -5
- package/dist/gg-call-sites-plugin.d.ts +90 -6
- package/dist/gg-call-sites-plugin.js +700 -112
- package/dist/gg.d.ts +18 -2
- package/dist/gg.js +127 -110
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/open-in-editor.js +15 -2
- package/dist/vite.d.ts +37 -0
- package/dist/vite.js +46 -0
- package/package.json +20 -13
- package/dist/debug-bundled.d.ts +0 -2
- package/dist/debug-bundled.js +0 -3
- package/dist/debug.d.ts +0 -2
- package/dist/debug.js +0 -15
- package/patches/debug@4.4.3.patch +0 -35
package/dist/gg.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import ErrorStackParser from 'error-stack-parser';
|
|
2
1
|
/**
|
|
3
2
|
* Hook for capturing gg() output (used by Eruda plugin)
|
|
4
3
|
*/
|
|
@@ -9,13 +8,16 @@ interface CapturedEntry {
|
|
|
9
8
|
message: string;
|
|
10
9
|
args: unknown[];
|
|
11
10
|
timestamp: number;
|
|
11
|
+
file?: string;
|
|
12
|
+
line?: number;
|
|
13
|
+
col?: number;
|
|
14
|
+
src?: string;
|
|
12
15
|
}
|
|
13
16
|
type OnLogCallback = (entry: CapturedEntry) => void;
|
|
14
17
|
export declare function gg(): {
|
|
15
18
|
fileName: string;
|
|
16
19
|
functionName: string;
|
|
17
20
|
url: string;
|
|
18
|
-
stack: ErrorStackParser.StackFrame[];
|
|
19
21
|
};
|
|
20
22
|
export declare function gg<T>(arg: T, ...args: unknown[]): T;
|
|
21
23
|
export declare namespace gg {
|
|
@@ -85,6 +87,20 @@ export declare function bg(color: string): ChainableColorFn;
|
|
|
85
87
|
export declare namespace gg {
|
|
86
88
|
let _onLog: OnLogCallback | null;
|
|
87
89
|
let ns: (nsLabel: string, ...args: unknown[]) => unknown;
|
|
90
|
+
let _ns: (options: {
|
|
91
|
+
ns: string;
|
|
92
|
+
file?: string;
|
|
93
|
+
line?: number;
|
|
94
|
+
col?: number;
|
|
95
|
+
src?: string;
|
|
96
|
+
}, ...args: unknown[]) => unknown;
|
|
97
|
+
let _o: (ns: string, file?: string, line?: number, col?: number, src?: string) => {
|
|
98
|
+
ns: string;
|
|
99
|
+
file?: string;
|
|
100
|
+
line?: number;
|
|
101
|
+
col?: number;
|
|
102
|
+
src?: string;
|
|
103
|
+
};
|
|
88
104
|
}
|
|
89
105
|
/**
|
|
90
106
|
* Run gg diagnostics and log configuration status
|
package/dist/gg.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import debugFactory from './debug.js';
|
|
2
|
-
import ErrorStackParser from 'error-stack-parser';
|
|
1
|
+
import debugFactory, {} from './debug/index.js';
|
|
3
2
|
import { BROWSER, DEV } from 'esm-env';
|
|
4
3
|
import { toWordTuple } from './words.js';
|
|
5
4
|
const _ggCallSitesPlugin = typeof __GG_TAG_PLUGIN__ !== 'undefined' ? __GG_TAG_PLUGIN__ : false;
|
|
@@ -9,23 +8,21 @@ const _ggCallSitesPlugin = typeof __GG_TAG_PLUGIN__ !== 'undefined' ? __GG_TAG_P
|
|
|
9
8
|
*/
|
|
10
9
|
function createGgDebugger(namespace) {
|
|
11
10
|
const dbg = debugFactory(namespace);
|
|
12
|
-
// Store the original formatArgs
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
// Store the original formatArgs
|
|
14
12
|
const originalFormatArgs = dbg.formatArgs;
|
|
15
13
|
// Override formatArgs to add padding to the namespace display
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
14
|
dbg.formatArgs = function (args) {
|
|
18
15
|
// Call original formatArgs first
|
|
19
16
|
if (originalFormatArgs) {
|
|
20
|
-
originalFormatArgs.call(
|
|
17
|
+
originalFormatArgs.call(dbg, args);
|
|
21
18
|
}
|
|
22
19
|
// Extract the callpoint from namespace (strip 'gg:' prefix and any URL suffix)
|
|
23
|
-
const nsMatch =
|
|
24
|
-
const callpoint = nsMatch ? nsMatch[1] :
|
|
20
|
+
const nsMatch = dbg.namespace.match(/^gg:([^h]+?)(?:http|$)/);
|
|
21
|
+
const callpoint = nsMatch ? nsMatch[1] : dbg.namespace.replace(/^gg:/, '');
|
|
25
22
|
const paddedCallpoint = callpoint.padEnd(maxCallpointLength, ' ');
|
|
26
23
|
// Replace the namespace in the formatted string with padded version
|
|
27
24
|
if (typeof args[0] === 'string') {
|
|
28
|
-
args[0] = args[0].replace(
|
|
25
|
+
args[0] = args[0].replace(dbg.namespace, `gg:${paddedCallpoint}`);
|
|
29
26
|
}
|
|
30
27
|
};
|
|
31
28
|
return dbg;
|
|
@@ -91,7 +88,6 @@ function getServerPort() {
|
|
|
91
88
|
}
|
|
92
89
|
});
|
|
93
90
|
}
|
|
94
|
-
const timestampRegex = /(\?t=\d+)?$/;
|
|
95
91
|
const port = await getServerPort();
|
|
96
92
|
/**
|
|
97
93
|
* Determines if gg should be enabled based on environment and runtime triggers.
|
|
@@ -169,6 +165,23 @@ const namespaceToLogFunction = new Map();
|
|
|
169
165
|
let maxCallpointLength = 0;
|
|
170
166
|
// Cache: raw stack line → word tuple (avoids re-hashing the same call site)
|
|
171
167
|
const stackLineCache = new Map();
|
|
168
|
+
/**
|
|
169
|
+
* Resolve the callpoint for the caller at the given stack depth.
|
|
170
|
+
* depth=2 → caller of gg(), depth=3 → caller of gg.ns() (extra frame).
|
|
171
|
+
*/
|
|
172
|
+
function resolveCallpoint(depth) {
|
|
173
|
+
const rawStack = new Error().stack || '';
|
|
174
|
+
const callerLine = rawStack.split('\n')[depth] || rawStack;
|
|
175
|
+
const callerKey = callerLine.replace(/:\d+:\d+\)?$/, '').trim();
|
|
176
|
+
const callpoint = stackLineCache.get(callerKey) ?? toWordTuple(callerKey);
|
|
177
|
+
if (!stackLineCache.has(callerKey)) {
|
|
178
|
+
stackLineCache.set(callerKey, callpoint);
|
|
179
|
+
}
|
|
180
|
+
if (callpoint.length < 80 && callpoint.length > maxCallpointLength) {
|
|
181
|
+
maxCallpointLength = callpoint.length;
|
|
182
|
+
}
|
|
183
|
+
return callpoint;
|
|
184
|
+
}
|
|
172
185
|
/**
|
|
173
186
|
* Reset the namespace width tracking.
|
|
174
187
|
* Useful after configuration checks that may have long callpoint paths.
|
|
@@ -176,80 +189,37 @@ const stackLineCache = new Map();
|
|
|
176
189
|
function resetNamespaceWidth() {
|
|
177
190
|
maxCallpointLength = 0;
|
|
178
191
|
}
|
|
179
|
-
function openInEditorUrl(fileName) {
|
|
180
|
-
|
|
192
|
+
function openInEditorUrl(fileName, line, col) {
|
|
193
|
+
let url = ggConfig.openInEditorUrlTemplate.replace('$FILENAME', encodeURIComponent(fileName).replaceAll('%2F', '/'));
|
|
194
|
+
if (line != null)
|
|
195
|
+
url += `&line=${line}`;
|
|
196
|
+
if (col != null)
|
|
197
|
+
url += `&col=${col}`;
|
|
198
|
+
return url;
|
|
181
199
|
}
|
|
182
200
|
export function gg(...args) {
|
|
183
201
|
if (!ggConfig.enabled || isCloudflareWorker()) {
|
|
184
|
-
return args.length ? args[0] : {
|
|
185
|
-
}
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// at build time, so this code path only runs for un-transformed calls.
|
|
194
|
-
// Skip expensive stack parsing if the plugin is handling callpoints.
|
|
195
|
-
if (!_ggCallSitesPlugin) {
|
|
196
|
-
if (DEV) {
|
|
197
|
-
// Development without plugin: full stack parsing for detailed callpoint info
|
|
198
|
-
// Ignore first stack frame, which is always the call to gg() itself.
|
|
199
|
-
stack = ErrorStackParser.parse(new Error()).splice(1);
|
|
200
|
-
// Example: http://localhost:5173/src/routes/+page.svelte
|
|
201
|
-
const filename = stack[0].fileName?.replace(timestampRegex, '') || '';
|
|
202
|
-
// Example: src/routes/+page.svelte
|
|
203
|
-
const filenameToOpen = filename.replace(srcRootRegex, '$<folderName>/');
|
|
204
|
-
url = openInEditorUrl(filenameToOpen);
|
|
205
|
-
// Example: routes/+page.svelte
|
|
206
|
-
fileName = filename.replace(srcRootRegex, '');
|
|
207
|
-
functionName = stack[0].functionName || '';
|
|
208
|
-
// A callpoint is uniquely identified by the filename plus function name
|
|
209
|
-
const callpoint = `${fileName}${functionName ? `@${functionName}` : ''}`;
|
|
210
|
-
if (callpoint.length < 80 && callpoint.length > maxCallpointLength) {
|
|
211
|
-
maxCallpointLength = callpoint.length;
|
|
212
|
-
}
|
|
213
|
-
// Namespace without padding - keeps colors stable
|
|
214
|
-
// Editor link appended if enabled
|
|
215
|
-
namespace = `gg:${callpoint}${ggConfig.editorLink ? url : ''}`;
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
// Production without plugin: cheap stack hash → deterministic word tuple
|
|
219
|
-
// Avoids expensive ErrorStackParser; just grabs the raw stack line and hashes it.
|
|
220
|
-
// Same call site always produces the same word pair (e.g. "calm-fox").
|
|
221
|
-
const rawStack = new Error().stack || '';
|
|
222
|
-
// Stack line [2]: skip "Error" header [0] and gg() frame [1]
|
|
223
|
-
const callerLine = rawStack.split('\n')[2] || rawStack;
|
|
224
|
-
// Strip line:col numbers so all gg() calls within the same function
|
|
225
|
-
// hash to the same word tuple. In minified builds, multiple gg() calls
|
|
226
|
-
// in one function differ only by column offset — we want them grouped.
|
|
227
|
-
// Chrome: "at handleClick (chunk-abc.js:1:45892)" → "at handleClick (chunk-abc.js)"
|
|
228
|
-
// Firefox: "handleClick@https://...:1:45892" → "handleClick@https://..."
|
|
229
|
-
const callerKey = callerLine.replace(/:\d+:\d+\)?$/, '').trim();
|
|
230
|
-
const callpoint = stackLineCache.get(callerKey) ?? toWordTuple(callerKey);
|
|
231
|
-
if (!stackLineCache.has(callerKey)) {
|
|
232
|
-
stackLineCache.set(callerKey, callpoint);
|
|
233
|
-
}
|
|
234
|
-
if (callpoint.length < 80 && callpoint.length > maxCallpointLength) {
|
|
235
|
-
maxCallpointLength = callpoint.length;
|
|
236
|
-
}
|
|
237
|
-
namespace = `gg:${callpoint}`;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
202
|
+
return args.length ? args[0] : { fileName: '', functionName: '', url: '' };
|
|
203
|
+
}
|
|
204
|
+
// Without the call-sites plugin, use cheap stack hash → deterministic word tuple.
|
|
205
|
+
// When the plugin IS installed, all gg() calls are rewritten to gg._ns() at build time,
|
|
206
|
+
// so this code path only runs for un-transformed calls (i.e. plugin not installed).
|
|
207
|
+
// Same call site always produces the same word pair (e.g. "calm-fox").
|
|
208
|
+
// depth=2: skip "Error" header [0] and gg() frame [1]
|
|
209
|
+
const callpoint = resolveCallpoint(2);
|
|
210
|
+
const namespace = `gg:${callpoint}`;
|
|
240
211
|
const ggLogFunction = namespaceToLogFunction.get(namespace) ||
|
|
241
212
|
namespaceToLogFunction.set(namespace, createGgDebugger(namespace)).get(namespace);
|
|
242
213
|
// Prepare args for logging
|
|
243
214
|
let logArgs;
|
|
244
215
|
let returnValue;
|
|
245
216
|
if (!args.length) {
|
|
246
|
-
// No arguments:
|
|
247
|
-
logArgs = [`
|
|
217
|
+
// No arguments: return stub call-site info (no open-in-editor without plugin)
|
|
218
|
+
logArgs = [` 📝 ${callpoint} (install gg-call-sites-plugin for editor links)`];
|
|
248
219
|
returnValue = {
|
|
249
|
-
fileName,
|
|
250
|
-
functionName,
|
|
251
|
-
url
|
|
252
|
-
stack
|
|
220
|
+
fileName: callpoint,
|
|
221
|
+
functionName: '',
|
|
222
|
+
url: ''
|
|
253
223
|
};
|
|
254
224
|
}
|
|
255
225
|
else if (args.length === 1) {
|
|
@@ -288,22 +258,54 @@ export function gg(...args) {
|
|
|
288
258
|
/**
|
|
289
259
|
* gg.ns() - Log with an explicit namespace (callpoint label).
|
|
290
260
|
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
261
|
+
* Users call gg.ns() directly to set a meaningful label that survives
|
|
262
|
+
* across builds. For the internal plugin-generated version with file
|
|
263
|
+
* metadata, see gg._ns().
|
|
264
|
+
*
|
|
265
|
+
* The label supports template variables (substituted by the vite plugin
|
|
266
|
+
* at build time, or at runtime for $NS):
|
|
267
|
+
* $NS - auto-generated callpoint (file@fn with plugin, word-tuple without)
|
|
268
|
+
* $FN - enclosing function name (plugin only, empty without)
|
|
269
|
+
* $FILE - short file path (plugin only, empty without)
|
|
270
|
+
* $LINE - line number (plugin only, empty without)
|
|
271
|
+
* $COL - column number (plugin only, empty without)
|
|
295
272
|
*
|
|
296
273
|
* @param nsLabel - The namespace label (appears as gg:<nsLabel> in output)
|
|
297
274
|
* @param args - Same arguments as gg()
|
|
298
275
|
* @returns Same as gg() - the first arg, or call-site info if no args
|
|
299
276
|
*
|
|
300
277
|
* @example
|
|
301
|
-
* gg.ns("auth", "login failed")
|
|
302
|
-
* gg.ns("
|
|
278
|
+
* gg.ns("auth", "login failed") // → gg:auth
|
|
279
|
+
* gg.ns("ERROR:$NS", msg) // → gg:ERROR:routes/+page.svelte@handleClick (with plugin)
|
|
280
|
+
* // → gg:ERROR:calm-fox (without plugin)
|
|
281
|
+
* gg.ns("$NS:validation", fieldName) // → gg:routes/+page.svelte@handleClick:validation
|
|
303
282
|
*/
|
|
304
283
|
gg.ns = function (nsLabel, ...args) {
|
|
284
|
+
// Resolve $NS at runtime (word-tuple fallback when plugin isn't installed).
|
|
285
|
+
// With the plugin, $NS is already substituted at build time before this runs.
|
|
286
|
+
// depth=3: skip "Error" [0], resolveCallpoint [1], gg.ns [2] → caller [3]
|
|
287
|
+
if (nsLabel.includes('$NS')) {
|
|
288
|
+
const callpoint = resolveCallpoint(3);
|
|
289
|
+
nsLabel = nsLabel.replace(/\$NS/g, callpoint);
|
|
290
|
+
}
|
|
291
|
+
return gg._ns({ ns: nsLabel }, ...args);
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* gg._ns() - Internal: log with namespace and source file metadata.
|
|
295
|
+
*
|
|
296
|
+
* Called by the ggCallSitesPlugin Vite plugin, which rewrites both bare gg()
|
|
297
|
+
* calls and manual gg.ns() calls to gg._ns({ns, file, line, col}, ...) at
|
|
298
|
+
* build time. This gives each call site a unique namespace plus the source
|
|
299
|
+
* location for open-in-editor support.
|
|
300
|
+
*
|
|
301
|
+
* @param options - { ns: string; file?: string; line?: number; col?: number }
|
|
302
|
+
* @param args - Same arguments as gg()
|
|
303
|
+
* @returns Same as gg() - the first arg, or call-site info if no args
|
|
304
|
+
*/
|
|
305
|
+
gg._ns = function (options, ...args) {
|
|
306
|
+
const { ns: nsLabel, file, line, col, src } = options;
|
|
305
307
|
if (!ggConfig.enabled || isCloudflareWorker()) {
|
|
306
|
-
return args.length ? args[0] : {
|
|
308
|
+
return args.length ? args[0] : { fileName: '', functionName: '', url: '' };
|
|
307
309
|
}
|
|
308
310
|
const namespace = `gg:${nsLabel}`;
|
|
309
311
|
if (nsLabel.length < 80 && nsLabel.length > maxCallpointLength) {
|
|
@@ -311,12 +313,17 @@ gg.ns = function (nsLabel, ...args) {
|
|
|
311
313
|
}
|
|
312
314
|
const ggLogFunction = namespaceToLogFunction.get(namespace) ||
|
|
313
315
|
namespaceToLogFunction.set(namespace, createGgDebugger(namespace)).get(namespace);
|
|
314
|
-
// Prepare args for logging
|
|
316
|
+
// Prepare args for logging (console output is value-only; src is carried
|
|
317
|
+
// on CapturedEntry for the Eruda UI to display on hover)
|
|
315
318
|
let logArgs;
|
|
316
319
|
let returnValue;
|
|
317
320
|
if (!args.length) {
|
|
321
|
+
// No arguments: return call-site info for open-in-editor
|
|
322
|
+
const fileName = file ? file.replace(srcRootRegex, '') : nsLabel;
|
|
323
|
+
const functionName = nsLabel.includes('@') ? nsLabel.split('@').pop() || '' : '';
|
|
324
|
+
const url = file ? openInEditorUrl(file, line, col) : '';
|
|
318
325
|
logArgs = [` 📝 ${nsLabel}`];
|
|
319
|
-
returnValue = { fileName
|
|
326
|
+
returnValue = { fileName, functionName, url };
|
|
320
327
|
}
|
|
321
328
|
else if (args.length === 1) {
|
|
322
329
|
logArgs = [args[0]];
|
|
@@ -340,7 +347,11 @@ gg.ns = function (nsLabel, ...args) {
|
|
|
340
347
|
diff: ggLogFunction.diff || 0,
|
|
341
348
|
message: logArgs.length === 1 ? String(logArgs[0]) : logArgs.map(String).join(' '),
|
|
342
349
|
args: logArgs,
|
|
343
|
-
timestamp: Date.now()
|
|
350
|
+
timestamp: Date.now(),
|
|
351
|
+
file,
|
|
352
|
+
line,
|
|
353
|
+
col,
|
|
354
|
+
src
|
|
344
355
|
};
|
|
345
356
|
if (_onLogCallback) {
|
|
346
357
|
_onLogCallback(entry);
|
|
@@ -350,6 +361,18 @@ gg.ns = function (nsLabel, ...args) {
|
|
|
350
361
|
}
|
|
351
362
|
return returnValue;
|
|
352
363
|
};
|
|
364
|
+
/**
|
|
365
|
+
* gg._o() - Internal: build options object for gg._ns() without object literal syntax.
|
|
366
|
+
*
|
|
367
|
+
* Used by the vite plugin to transform gg() calls in Svelte template markup,
|
|
368
|
+
* where object literals ({...}) would break Svelte's template parser.
|
|
369
|
+
*
|
|
370
|
+
* In <script> blocks: gg._ns({ns:'...', file:'...', line:1, col:1}, args)
|
|
371
|
+
* In template markup: gg._ns(gg._o('...','...',1,1), args)
|
|
372
|
+
*/
|
|
373
|
+
gg._o = function (ns, file, line, col, src) {
|
|
374
|
+
return { ns, file, line, col, src };
|
|
375
|
+
};
|
|
353
376
|
gg.disable = isCloudflareWorker() ? () => { } : debugFactory.disable;
|
|
354
377
|
gg.enable = isCloudflareWorker() ? () => { } : debugFactory.enable;
|
|
355
378
|
/**
|
|
@@ -506,26 +529,28 @@ Object.defineProperty(gg, '_onLog', {
|
|
|
506
529
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
507
530
|
(function (gg) {
|
|
508
531
|
})(gg || (gg = {}));
|
|
532
|
+
// Track if diagnostics have already run to prevent double execution
|
|
533
|
+
let diagnosticsRan = false;
|
|
509
534
|
/**
|
|
510
535
|
* Run gg diagnostics and log configuration status
|
|
511
536
|
* Can be called immediately or delayed (e.g., after Eruda loads)
|
|
512
537
|
*/
|
|
513
538
|
export async function runGgDiagnostics() {
|
|
514
|
-
if (!ggConfig.showHints || isCloudflareWorker())
|
|
539
|
+
if (!ggConfig.showHints || isCloudflareWorker() || diagnosticsRan)
|
|
515
540
|
return;
|
|
541
|
+
diagnosticsRan = true;
|
|
542
|
+
// Create test debugger for server-side enabled check
|
|
516
543
|
const ggLogTest = debugFactory('gg:TEST');
|
|
517
544
|
let ggMessage = '\n';
|
|
518
|
-
// Utilities for forming ggMessage:
|
|
519
545
|
const message = (s) => (ggMessage += `${s}\n`);
|
|
520
546
|
const checkbox = (test) => (test ? '✅' : '❌');
|
|
521
547
|
const makeHint = (test, ifTrue, ifFalse = '') => (test ? ifTrue : ifFalse);
|
|
522
|
-
// Use plain console.log for diagnostics - appears in Eruda's Console tab
|
|
523
548
|
console.log(`Loaded gg module. Checking configuration...`);
|
|
524
|
-
|
|
525
|
-
|
|
549
|
+
const configOk = BROWSER ? ggConfig.enabled : ggConfig.enabled && ggLogTest.enabled;
|
|
550
|
+
if (configOk) {
|
|
526
551
|
message(`No problems detected:`);
|
|
527
552
|
if (BROWSER) {
|
|
528
|
-
message(`ℹ️
|
|
553
|
+
message(`ℹ️ gg messages appear in the Eruda GG panel. Use Settings > Native Console to also show in browser console.`);
|
|
529
554
|
}
|
|
530
555
|
}
|
|
531
556
|
else {
|
|
@@ -541,35 +566,27 @@ export async function runGgDiagnostics() {
|
|
|
541
566
|
}
|
|
542
567
|
}
|
|
543
568
|
message(`${checkbox(ggConfig.enabled)} gg enabled: ${ggConfig.enabled}${enableHint}`);
|
|
544
|
-
if (BROWSER) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
const hint = makeHint(!ggLogTest.enabled, ' (Try `DEBUG=gg:* npm dev`)');
|
|
569
|
+
if (!BROWSER) {
|
|
570
|
+
// Server-side: check DEBUG env var (the only output path on the server)
|
|
571
|
+
const hint = makeHint(!ggLogTest.enabled, ' (Try `DEBUG=gg:* npm run dev`)');
|
|
550
572
|
if (dotenvModule) {
|
|
551
|
-
dotenvModule.config();
|
|
573
|
+
dotenvModule.config();
|
|
552
574
|
}
|
|
553
575
|
message(`${checkbox(ggLogTest.enabled)} DEBUG env variable: ${process?.env?.DEBUG}${hint}`);
|
|
554
576
|
}
|
|
555
|
-
// Optional plugin diagnostics
|
|
556
|
-
message(makeHint(_ggCallSitesPlugin, `✅
|
|
577
|
+
// Optional plugin diagnostics
|
|
578
|
+
message(makeHint(_ggCallSitesPlugin, `✅ gg-call-sites vite plugin detected! Call-site namespaces and open-in-editor links baked in at build time.`, `⚠️ gg-call-sites vite plugin not detected. Add ggCallSitesPlugin() to vite.config.ts for file:line call-site namespaces and open-in-editor links. Without plugin, using word-tuple names (e.g. calm-fox) as call-site identifiers.`));
|
|
557
579
|
if (BROWSER && DEV) {
|
|
558
580
|
const { status } = await fetch('/__open-in-editor?file=+');
|
|
559
581
|
message(makeHint(status === 222, `✅ (optional) open-in-editor vite plugin detected! (status code: ${status}) Clickable links open source files in editor.`, `⚠️ (optional) open-in-editor vite plugin not detected. (status code: ${status}) Add openInEditorPlugin() to vite.config.ts for clickable links that open source files in editor`));
|
|
560
582
|
}
|
|
561
|
-
// Use plain console.log for diagnostics - appears in Eruda's Console tab
|
|
562
583
|
console.log(ggMessage);
|
|
563
|
-
// Reset namespace width after configuration check
|
|
564
|
-
// This prevents the long callpoint from the config check from affecting subsequent logs
|
|
565
584
|
resetNamespaceWidth();
|
|
566
585
|
}
|
|
567
|
-
// Run diagnostics immediately on module load
|
|
568
|
-
//
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
runGgDiagnostics();
|
|
574
|
-
}
|
|
586
|
+
// Run diagnostics immediately on module load ONLY in Node.js environments
|
|
587
|
+
// In browser, the Eruda loader (if configured) will call runGgDiagnostics()
|
|
588
|
+
// after Eruda is ready. If Eruda is not configured, diagnostics won't run
|
|
589
|
+
// in browser (user must manually check console or call runGgDiagnostics()).
|
|
590
|
+
if (ggConfig.showHints && !isCloudflareWorker() && !BROWSER) {
|
|
591
|
+
runGgDiagnostics();
|
|
575
592
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { gg, fg, bg } from './gg.js';
|
|
2
2
|
import openInEditorPlugin from './open-in-editor.js';
|
|
3
3
|
import ggCallSitesPlugin from './gg-call-sites-plugin.js';
|
|
4
|
+
export { default as GgConsole } from './GgConsole.svelte';
|
|
4
5
|
export { gg, fg, bg, openInEditorPlugin, ggCallSitesPlugin };
|
package/dist/index.js
CHANGED
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
import { gg, fg, bg } from './gg.js';
|
|
3
3
|
import openInEditorPlugin from './open-in-editor.js';
|
|
4
4
|
import ggCallSitesPlugin from './gg-call-sites-plugin.js';
|
|
5
|
+
export { default as GgConsole } from './GgConsole.svelte';
|
|
5
6
|
export { gg, fg, bg, openInEditorPlugin, ggCallSitesPlugin };
|
package/dist/open-in-editor.js
CHANGED
|
@@ -16,17 +16,30 @@ export default function openInEditorPlugin(specifiedEditor, srcRoot, onErrorCall
|
|
|
16
16
|
name: 'open-in-editor',
|
|
17
17
|
configureServer(server) {
|
|
18
18
|
server.middlewares.use('/__open-in-editor', (req, res) => {
|
|
19
|
-
const { file } = url.parse(req.url || '', true).query || {};
|
|
19
|
+
const { file, line, col, editor } = url.parse(req.url || '', true).query || {};
|
|
20
20
|
if (!file) {
|
|
21
21
|
res.statusCode = 500;
|
|
22
22
|
res.end(`open-in-editor-plugin: required query param "file" is missing.`);
|
|
23
23
|
}
|
|
24
24
|
else {
|
|
25
25
|
res.statusCode = 222;
|
|
26
|
-
launch
|
|
26
|
+
// launch-editor supports file:line:col format for cursor positioning
|
|
27
|
+
let fileArg = path.resolve(srcRoot, file);
|
|
28
|
+
if (line)
|
|
29
|
+
fileArg += `:${line}`;
|
|
30
|
+
if (line && col)
|
|
31
|
+
fileArg += `:${col}`;
|
|
32
|
+
// Use editor from query param if provided, otherwise fall back to plugin config
|
|
33
|
+
const editorToUse = typeof editor === 'string' && editor ? editor : specifiedEditor;
|
|
34
|
+
launch(fileArg, editorToUse, onErrorCallback);
|
|
27
35
|
res.end('<p>You may safely close this window.</p><script>window.close()</script>');
|
|
28
36
|
}
|
|
29
37
|
});
|
|
38
|
+
// Expose project root for client-side $ROOT variable (forward slashes for URI compat)
|
|
39
|
+
server.middlewares.use('/__gg-project-root', (_req, res) => {
|
|
40
|
+
res.setHeader('Content-Type', 'text/plain');
|
|
41
|
+
res.end(srcRoot.replace(/\\/g, '/'));
|
|
42
|
+
});
|
|
30
43
|
}
|
|
31
44
|
};
|
|
32
45
|
}
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import ggCallSitesPlugin from './gg-call-sites-plugin.js';
|
|
3
|
+
import type { GgCallSitesPluginOptions } from './gg-call-sites-plugin.js';
|
|
4
|
+
import openInEditorPlugin from './open-in-editor.js';
|
|
5
|
+
export interface GgPluginsOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Options for the call-sites Vite plugin (source metadata rewriting).
|
|
8
|
+
* @default {}
|
|
9
|
+
*/
|
|
10
|
+
callSites?: GgCallSitesPluginOptions;
|
|
11
|
+
/**
|
|
12
|
+
* Enable the open-in-editor Vite plugin (dev server middleware).
|
|
13
|
+
* Set to `false` to disable.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
openInEditor?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* All gg Vite plugins bundled together.
|
|
20
|
+
*
|
|
21
|
+
* Includes:
|
|
22
|
+
* - `ggCallSitesPlugin` — rewrites `gg()` calls with source file/line/col metadata
|
|
23
|
+
* - `openInEditorPlugin` — adds `/__open-in-editor` dev server middleware
|
|
24
|
+
* - Automatic `es2022` build target (required for top-level await)
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import ggPlugins from '@leftium/gg/vite';
|
|
29
|
+
*
|
|
30
|
+
* export default defineConfig({
|
|
31
|
+
* plugins: [sveltekit(), ...ggPlugins()]
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export default function ggPlugins(options?: GgPluginsOptions): Plugin[];
|
|
36
|
+
export { ggCallSitesPlugin, openInEditorPlugin };
|
|
37
|
+
export type { GgCallSitesPluginOptions };
|
package/dist/vite.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import ggCallSitesPlugin from './gg-call-sites-plugin.js';
|
|
2
|
+
import openInEditorPlugin from './open-in-editor.js';
|
|
3
|
+
/**
|
|
4
|
+
* All gg Vite plugins bundled together.
|
|
5
|
+
*
|
|
6
|
+
* Includes:
|
|
7
|
+
* - `ggCallSitesPlugin` — rewrites `gg()` calls with source file/line/col metadata
|
|
8
|
+
* - `openInEditorPlugin` — adds `/__open-in-editor` dev server middleware
|
|
9
|
+
* - Automatic `es2022` build target (required for top-level await)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import ggPlugins from '@leftium/gg/vite';
|
|
14
|
+
*
|
|
15
|
+
* export default defineConfig({
|
|
16
|
+
* plugins: [sveltekit(), ...ggPlugins()]
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export default function ggPlugins(options = {}) {
|
|
21
|
+
const plugins = [];
|
|
22
|
+
// Ensure es2022 target for top-level await support
|
|
23
|
+
plugins.push({
|
|
24
|
+
name: 'gg-config',
|
|
25
|
+
config() {
|
|
26
|
+
return {
|
|
27
|
+
build: {
|
|
28
|
+
target: 'es2022'
|
|
29
|
+
},
|
|
30
|
+
optimizeDeps: {
|
|
31
|
+
esbuildOptions: {
|
|
32
|
+
target: 'es2022',
|
|
33
|
+
supported: { 'top-level-await': true }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
plugins.push(ggCallSitesPlugin(options.callSites));
|
|
40
|
+
if (options.openInEditor !== false) {
|
|
41
|
+
plugins.push(openInEditorPlugin());
|
|
42
|
+
}
|
|
43
|
+
return plugins;
|
|
44
|
+
}
|
|
45
|
+
// Allow granular imports for advanced users
|
|
46
|
+
export { ggCallSitesPlugin, openInEditorPlugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leftium/gg",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.34",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/Leftium/gg.git"
|
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
11
|
"!dist/**/*.test.*",
|
|
12
|
-
"!dist/**/*.spec.*"
|
|
13
|
-
"!dist/debug/",
|
|
14
|
-
"patches/"
|
|
12
|
+
"!dist/**/*.spec.*"
|
|
15
13
|
],
|
|
16
14
|
"sideEffects": [
|
|
17
15
|
"**/*.css"
|
|
@@ -21,8 +19,13 @@
|
|
|
21
19
|
"exports": {
|
|
22
20
|
".": {
|
|
23
21
|
"types": "./dist/index.d.ts",
|
|
22
|
+
"svelte": "./dist/index.js",
|
|
24
23
|
"default": "./dist/index.js"
|
|
25
24
|
},
|
|
25
|
+
"./vite": {
|
|
26
|
+
"types": "./dist/vite.d.ts",
|
|
27
|
+
"default": "./dist/vite.js"
|
|
28
|
+
},
|
|
26
29
|
"./eruda": {
|
|
27
30
|
"types": "./dist/eruda/index.d.ts",
|
|
28
31
|
"default": "./dist/eruda/index.js"
|
|
@@ -31,21 +34,21 @@
|
|
|
31
34
|
"peerDependencies": {
|
|
32
35
|
"svelte": "^5.0.0"
|
|
33
36
|
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"svelte": {
|
|
39
|
+
"optional": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
34
42
|
"devDependencies": {
|
|
35
43
|
"@eslint/compat": "^2.0.2",
|
|
36
44
|
"@eslint/js": "^10.0.1",
|
|
37
45
|
"@picocss/pico": "^2.1.1",
|
|
38
|
-
"@rollup/plugin-commonjs": "^29.0.0",
|
|
39
|
-
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
40
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
41
46
|
"@sveltejs/adapter-vercel": "^6.3.1",
|
|
42
47
|
"@sveltejs/kit": "^2.50.2",
|
|
43
48
|
"@sveltejs/package": "^2.5.7",
|
|
44
49
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
45
|
-
"@types/debug": "^4.1.12",
|
|
46
50
|
"@types/node": "^25.2.2",
|
|
47
51
|
"add": "^2.0.6",
|
|
48
|
-
"debug": "^4.4.3",
|
|
49
52
|
"eruda": "^3.4.3",
|
|
50
53
|
"eslint": "^10.0.0",
|
|
51
54
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -54,21 +57,23 @@
|
|
|
54
57
|
"prettier": "^3.8.1",
|
|
55
58
|
"prettier-plugin-svelte": "^3.4.1",
|
|
56
59
|
"publint": "^0.3.17",
|
|
57
|
-
"rollup": "^4.57.1",
|
|
58
60
|
"supports-color": "^10.2.2",
|
|
59
61
|
"svelte": "^5.50.1",
|
|
60
62
|
"svelte-check": "^4.3.6",
|
|
61
63
|
"typescript": "^5.9.3",
|
|
62
64
|
"typescript-eslint": "^8.55.0",
|
|
63
65
|
"vite": "^7.3.1",
|
|
64
|
-
"vite-plugin-devtools-json": "^1.0.0"
|
|
66
|
+
"vite-plugin-devtools-json": "^1.0.0",
|
|
67
|
+
"vitest": "^4.0.18"
|
|
65
68
|
},
|
|
66
69
|
"keywords": [
|
|
67
70
|
"svelte"
|
|
68
71
|
],
|
|
69
72
|
"dependencies": {
|
|
73
|
+
"@sveltejs/acorn-typescript": "^1.0.9",
|
|
74
|
+
"@types/estree": "^1.0.8",
|
|
75
|
+
"acorn": "^8.15.0",
|
|
70
76
|
"dotenv": "^17.2.4",
|
|
71
|
-
"error-stack-parser": "^2.1.4",
|
|
72
77
|
"esm-env": "^1.2.2",
|
|
73
78
|
"launch-editor": "^2.12.0"
|
|
74
79
|
},
|
|
@@ -79,6 +84,8 @@
|
|
|
79
84
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
80
85
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
81
86
|
"format": "prettier --write .",
|
|
82
|
-
"lint": "prettier --check . && eslint ."
|
|
87
|
+
"lint": "prettier --check . && eslint .",
|
|
88
|
+
"test": "vitest run",
|
|
89
|
+
"test:watch": "vitest"
|
|
83
90
|
}
|
|
84
91
|
}
|
package/dist/debug-bundled.d.ts
DELETED