@leftium/gg 0.0.21 → 0.0.23

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/dist/gg.d.ts CHANGED
@@ -1,4 +1,16 @@
1
1
  import ErrorStackParser from 'error-stack-parser';
2
+ /**
3
+ * Hook for capturing gg() output (used by Eruda plugin)
4
+ */
5
+ interface CapturedEntry {
6
+ namespace: string;
7
+ color: string;
8
+ diff: number;
9
+ message: string;
10
+ args: unknown[];
11
+ timestamp: number;
12
+ }
13
+ type OnLogCallback = (entry: CapturedEntry) => void;
2
14
  export declare function gg(): {
3
15
  fileName: string;
4
16
  functionName: string;
@@ -9,4 +21,7 @@ export declare function gg<T>(arg: T, ...args: unknown[]): T;
9
21
  export declare namespace gg {
10
22
  var disable: () => void;
11
23
  var enable: (namespaces: string) => void;
24
+ var clearPersist: () => void;
25
+ var _onLog: OnLogCallback | null;
12
26
  }
27
+ export {};
package/dist/gg.js CHANGED
@@ -64,8 +64,64 @@ function getServerPort() {
64
64
  }
65
65
  const timestampRegex = /(\?t=\d+)?$/;
66
66
  const port = await getServerPort();
67
+ /**
68
+ * Determines if gg should be enabled based on environment and runtime triggers.
69
+ *
70
+ * Priority order:
71
+ * 1. CloudFlare Workers → always disabled (no stack traces, no filesystem)
72
+ * 2. ENV hard-disable → absolute override, no runtime enable possible
73
+ * 3. DEV mode → always enabled
74
+ * 4. PROD mode → requires runtime trigger (?gg URL param or localStorage)
75
+ */
76
+ function isGgEnabled() {
77
+ // CloudFlare Workers - hard disable (no Error stacks, no filesystem)
78
+ if (isCloudflareWorker())
79
+ return false;
80
+ // ENV hard-disable takes absolute precedence
81
+ // Allows completely removing gg from production builds
82
+ if (BROWSER) {
83
+ if (typeof import.meta.env?.VITE_GG_ENABLED === 'string' &&
84
+ import.meta.env.VITE_GG_ENABLED === 'false') {
85
+ return false;
86
+ }
87
+ }
88
+ else {
89
+ if (process?.env?.GG_ENABLED === 'false') {
90
+ return false;
91
+ }
92
+ }
93
+ // Development - always enabled (unless ENV explicitly disabled above)
94
+ if (DEV)
95
+ return true;
96
+ // Production - requires runtime trigger (similar to Eruda widget loading)
97
+ if (BROWSER) {
98
+ // Check URL param (?gg)
99
+ try {
100
+ const params = new URLSearchParams(window.location.search);
101
+ if (params.has('gg')) {
102
+ // Persist the decision so it survives navigation
103
+ localStorage.setItem('gg-enabled', 'true');
104
+ return true;
105
+ }
106
+ }
107
+ catch {
108
+ // URLSearchParams or localStorage might not be available
109
+ }
110
+ // Check localStorage persistence
111
+ try {
112
+ if (localStorage.getItem('gg-enabled') === 'true') {
113
+ return true;
114
+ }
115
+ }
116
+ catch {
117
+ // localStorage might not be available
118
+ }
119
+ }
120
+ // Default: disabled in production without trigger
121
+ return false;
122
+ }
67
123
  const ggConfig = {
68
- enabled: !isCloudflareWorker(), // Disable in CloudFlare Workers
124
+ enabled: isGgEnabled(),
69
125
  showHints: !isCloudflareWorker(), // Don't show hints in CloudFlare Workers
70
126
  editorLink: false,
71
127
  openInEditorUrlTemplate: `http://localhost:${port}/__open-in-editor?file=$FILENAME`,
@@ -140,10 +196,43 @@ export function gg(...args) {
140
196
  else {
141
197
  ggLogFunction(args[0], ...args.slice(1));
142
198
  }
199
+ // Call capture hook if registered (for Eruda plugin)
200
+ if (gg._onLog) {
201
+ // Don't stringify args - keep them as-is for expandable objects
202
+ const message = args.length === 1 ? String(args[0]) : args.map(String).join(' ');
203
+ gg._onLog({
204
+ namespace,
205
+ color: ggLogFunction.color,
206
+ diff: ggLogFunction.diff || 0, // Millisecond diff from debug library
207
+ message,
208
+ args, // Keep raw args for object inspection
209
+ timestamp: Date.now()
210
+ });
211
+ }
143
212
  return args[0];
144
213
  }
145
214
  gg.disable = isCloudflareWorker() ? () => { } : debugFactory.disable;
146
215
  gg.enable = isCloudflareWorker() ? () => { } : debugFactory.enable;
216
+ /**
217
+ * Clear the persisted gg-enabled state from localStorage.
218
+ * Useful to reset production trigger after testing with ?gg parameter.
219
+ * Page reload required for change to take effect.
220
+ */
221
+ gg.clearPersist = () => {
222
+ if (BROWSER) {
223
+ try {
224
+ localStorage.removeItem('gg-enabled');
225
+ }
226
+ catch {
227
+ // localStorage might not be available
228
+ }
229
+ }
230
+ };
231
+ /**
232
+ * Hook for capturing gg() output (used by Eruda plugin)
233
+ * Set this to a callback function to receive log entries
234
+ */
235
+ gg._onLog = null;
147
236
  // Log some gg info to the JS console/terminal:
148
237
  if (ggConfig.showHints && !isCloudflareWorker()) {
149
238
  const ggLogTest = debugFactory('gg:TEST');
@@ -163,8 +252,16 @@ if (ggConfig.showHints && !isCloudflareWorker()) {
163
252
  else {
164
253
  message(`Problems detected; fix all ❌:`);
165
254
  }
166
- const hint = makeHint(!ggConfig.enabled, ' (Update value in gg.ts file.)');
167
- message(`${checkbox(ggConfig.enabled)} ggConfig.enabled: ${ggConfig.enabled}${hint}`);
255
+ let enableHint = '';
256
+ if (!ggConfig.enabled) {
257
+ if (DEV) {
258
+ enableHint = ' (Check GG_ENABLED env variable)';
259
+ }
260
+ else if (BROWSER) {
261
+ enableHint = ' (Add ?gg to URL or set localStorage["gg-enabled"]="true")';
262
+ }
263
+ }
264
+ message(`${checkbox(ggConfig.enabled)} gg enabled: ${ggConfig.enabled}${enableHint}`);
168
265
  if (BROWSER) {
169
266
  const hint = makeHint(!ggLogTest.enabled, " (Try `localStorage.debug = 'gg:*'`)");
170
267
  message(`${checkbox(ggLogTest.enabled)} localStorage.debug: ${localStorage?.debug}${hint}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leftium/gg",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Leftium/gg.git"
@@ -10,6 +10,7 @@
10
10
  "dist",
11
11
  "!dist/**/*.test.*",
12
12
  "!dist/**/*.spec.*",
13
+ "!dist/debug/",
13
14
  "patches/"
14
15
  ],
15
16
  "sideEffects": [
@@ -21,38 +22,44 @@
21
22
  ".": {
22
23
  "types": "./dist/index.d.ts",
23
24
  "default": "./dist/index.js"
25
+ },
26
+ "./eruda": {
27
+ "types": "./dist/eruda/index.d.ts",
28
+ "default": "./dist/eruda/index.js"
24
29
  }
25
30
  },
26
31
  "peerDependencies": {
27
32
  "svelte": "^5.0.0"
28
33
  },
29
34
  "devDependencies": {
30
- "@eslint/compat": "^2.0.1",
31
- "@eslint/js": "^9.39.2",
35
+ "@eslint/compat": "^2.0.2",
36
+ "@eslint/js": "^10.0.1",
32
37
  "@picocss/pico": "^2.1.1",
33
38
  "@rollup/plugin-commonjs": "^29.0.0",
34
39
  "@rollup/plugin-node-resolve": "^16.0.3",
35
40
  "@rollup/plugin-terser": "^0.4.4",
36
- "@sveltejs/adapter-vercel": "^6.3.0",
37
- "@sveltejs/kit": "^2.49.4",
41
+ "@sveltejs/adapter-vercel": "^6.3.1",
42
+ "@sveltejs/kit": "^2.50.2",
38
43
  "@sveltejs/package": "^2.5.7",
39
44
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
40
45
  "@types/debug": "^4.1.12",
41
- "@types/node": "^25.0.8",
46
+ "@types/node": "^25.2.2",
42
47
  "add": "^2.0.6",
43
48
  "debug": "^4.4.3",
44
- "eslint": "^9.39.2",
49
+ "eruda": "^3.4.3",
50
+ "eslint": "^10.0.0",
45
51
  "eslint-config-prettier": "^10.1.8",
46
52
  "eslint-plugin-svelte": "^3.14.0",
47
- "globals": "^17.0.0",
48
- "prettier": "^3.7.4",
53
+ "globals": "^17.3.0",
54
+ "prettier": "^3.8.1",
49
55
  "prettier-plugin-svelte": "^3.4.1",
50
- "publint": "^0.3.16",
56
+ "publint": "^0.3.17",
57
+ "rollup": "^4.57.1",
51
58
  "supports-color": "^10.2.2",
52
- "svelte": "^5.46.3",
53
- "svelte-check": "^4.3.5",
59
+ "svelte": "^5.50.1",
60
+ "svelte-check": "^4.3.6",
54
61
  "typescript": "^5.9.3",
55
- "typescript-eslint": "^8.53.0",
62
+ "typescript-eslint": "^8.55.0",
56
63
  "vite": "^7.3.1",
57
64
  "vite-plugin-devtools-json": "^1.0.0"
58
65
  },
@@ -60,7 +67,7 @@
60
67
  "svelte"
61
68
  ],
62
69
  "dependencies": {
63
- "dotenv": "^17.2.3",
70
+ "dotenv": "^17.2.4",
64
71
  "error-stack-parser": "^2.1.4",
65
72
  "esm-env": "^1.2.2",
66
73
  "launch-editor": "^2.12.0"
@@ -1,2 +0,0 @@
1
- declare function _exports(val: string | number, options?: Object): string | number;
2
- export = _exports;
@@ -1,162 +0,0 @@
1
- /**
2
- * Helpers.
3
- */
4
-
5
- var s = 1000;
6
- var m = s * 60;
7
- var h = m * 60;
8
- var d = h * 24;
9
- var w = d * 7;
10
- var y = d * 365.25;
11
-
12
- /**
13
- * Parse or format the given `val`.
14
- *
15
- * Options:
16
- *
17
- * - `long` verbose formatting [false]
18
- *
19
- * @param {String|Number} val
20
- * @param {Object} [options]
21
- * @throws {Error} throw an error if val is not a non-empty string or a number
22
- * @return {String|Number}
23
- * @api public
24
- */
25
-
26
- module.exports = function (val, options) {
27
- options = options || {};
28
- var type = typeof val;
29
- if (type === 'string' && val.length > 0) {
30
- return parse(val);
31
- } else if (type === 'number' && isFinite(val)) {
32
- return options.long ? fmtLong(val) : fmtShort(val);
33
- }
34
- throw new Error(
35
- 'val is not a non-empty string or a valid number. val=' +
36
- JSON.stringify(val)
37
- );
38
- };
39
-
40
- /**
41
- * Parse the given `str` and return milliseconds.
42
- *
43
- * @param {String} str
44
- * @return {Number}
45
- * @api private
46
- */
47
-
48
- function parse(str) {
49
- str = String(str);
50
- if (str.length > 100) {
51
- return;
52
- }
53
- var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
54
- str
55
- );
56
- if (!match) {
57
- return;
58
- }
59
- var n = parseFloat(match[1]);
60
- var type = (match[2] || 'ms').toLowerCase();
61
- switch (type) {
62
- case 'years':
63
- case 'year':
64
- case 'yrs':
65
- case 'yr':
66
- case 'y':
67
- return n * y;
68
- case 'weeks':
69
- case 'week':
70
- case 'w':
71
- return n * w;
72
- case 'days':
73
- case 'day':
74
- case 'd':
75
- return n * d;
76
- case 'hours':
77
- case 'hour':
78
- case 'hrs':
79
- case 'hr':
80
- case 'h':
81
- return n * h;
82
- case 'minutes':
83
- case 'minute':
84
- case 'mins':
85
- case 'min':
86
- case 'm':
87
- return n * m;
88
- case 'seconds':
89
- case 'second':
90
- case 'secs':
91
- case 'sec':
92
- case 's':
93
- return n * s;
94
- case 'milliseconds':
95
- case 'millisecond':
96
- case 'msecs':
97
- case 'msec':
98
- case 'ms':
99
- return n;
100
- default:
101
- return undefined;
102
- }
103
- }
104
-
105
- /**
106
- * Short format for `ms`.
107
- *
108
- * @param {Number} ms
109
- * @return {String}
110
- * @api private
111
- */
112
-
113
- function fmtShort(ms) {
114
- var msAbs = Math.abs(ms);
115
- if (msAbs >= d) {
116
- return Math.round(ms / d) + 'd';
117
- }
118
- if (msAbs >= h) {
119
- return Math.round(ms / h) + 'h';
120
- }
121
- if (msAbs >= m) {
122
- return Math.round(ms / m) + 'm';
123
- }
124
- if (msAbs >= s) {
125
- return Math.round(ms / s) + 's';
126
- }
127
- return ms + 'ms';
128
- }
129
-
130
- /**
131
- * Long format for `ms`.
132
- *
133
- * @param {Number} ms
134
- * @return {String}
135
- * @api private
136
- */
137
-
138
- function fmtLong(ms) {
139
- var msAbs = Math.abs(ms);
140
- if (msAbs >= d) {
141
- return plural(ms, msAbs, d, 'day');
142
- }
143
- if (msAbs >= h) {
144
- return plural(ms, msAbs, h, 'hour');
145
- }
146
- if (msAbs >= m) {
147
- return plural(ms, msAbs, m, 'minute');
148
- }
149
- if (msAbs >= s) {
150
- return plural(ms, msAbs, s, 'second');
151
- }
152
- return ms + ' ms';
153
- }
154
-
155
- /**
156
- * Pluralization helper.
157
- */
158
-
159
- function plural(ms, msAbs, n, name) {
160
- var isPlural = msAbs >= n * 1.5;
161
- return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
162
- }
@@ -1,38 +0,0 @@
1
- {
2
- "name": "ms",
3
- "version": "2.1.3",
4
- "description": "Tiny millisecond conversion utility",
5
- "repository": "vercel/ms",
6
- "main": "./index",
7
- "files": [
8
- "index.js"
9
- ],
10
- "scripts": {
11
- "precommit": "lint-staged",
12
- "lint": "eslint lib/* bin/*",
13
- "test": "mocha tests.js"
14
- },
15
- "eslintConfig": {
16
- "extends": "eslint:recommended",
17
- "env": {
18
- "node": true,
19
- "es6": true
20
- }
21
- },
22
- "lint-staged": {
23
- "*.js": [
24
- "npm run lint",
25
- "prettier --single-quote --write",
26
- "git add"
27
- ]
28
- },
29
- "license": "MIT",
30
- "devDependencies": {
31
- "eslint": "4.18.2",
32
- "expect.js": "0.3.1",
33
- "husky": "0.14.3",
34
- "lint-staged": "5.0.0",
35
- "mocha": "4.0.1",
36
- "prettier": "2.0.5"
37
- }
38
- }
@@ -1,64 +0,0 @@
1
- {
2
- "name": "debug",
3
- "version": "4.4.3",
4
- "repository": {
5
- "type": "git",
6
- "url": "git://github.com/debug-js/debug.git"
7
- },
8
- "description": "Lightweight debugging utility for Node.js and the browser",
9
- "keywords": [
10
- "debug",
11
- "log",
12
- "debugger"
13
- ],
14
- "files": [
15
- "src",
16
- "LICENSE",
17
- "README.md"
18
- ],
19
- "author": "Josh Junon (https://github.com/qix-)",
20
- "contributors": [
21
- "TJ Holowaychuk <tj@vision-media.ca>",
22
- "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
23
- "Andrew Rhyne <rhyneandrew@gmail.com>"
24
- ],
25
- "license": "MIT",
26
- "scripts": {
27
- "lint": "xo",
28
- "test": "npm run test:node && npm run test:browser && npm run lint",
29
- "test:node": "mocha test.js test.node.js",
30
- "test:browser": "karma start --single-run",
31
- "test:coverage": "cat ./coverage/lcov.info | coveralls"
32
- },
33
- "dependencies": {
34
- "ms": "^2.1.3"
35
- },
36
- "devDependencies": {
37
- "brfs": "^2.0.1",
38
- "browserify": "^16.2.3",
39
- "coveralls": "^3.0.2",
40
- "karma": "^3.1.4",
41
- "karma-browserify": "^6.0.0",
42
- "karma-chrome-launcher": "^2.2.0",
43
- "karma-mocha": "^1.3.0",
44
- "mocha": "^5.2.0",
45
- "mocha-lcov-reporter": "^1.2.0",
46
- "sinon": "^14.0.0",
47
- "xo": "^0.23.0"
48
- },
49
- "peerDependenciesMeta": {
50
- "supports-color": {
51
- "optional": true
52
- }
53
- },
54
- "main": "./src/index.js",
55
- "browser": "./src/browser.js",
56
- "engines": {
57
- "node": ">=6.0"
58
- },
59
- "xo": {
60
- "rules": {
61
- "import/extensions": "off"
62
- }
63
- }
64
- }
@@ -1,90 +0,0 @@
1
- declare const _exports: {
2
- (namespace: string): Function;
3
- debug: {
4
- (namespace: string): Function;
5
- debug: /*elided*/ any;
6
- default: /*elided*/ any;
7
- coerce: (val: Mixed) => Mixed;
8
- disable: () => string;
9
- enable: (namespaces: string) => void;
10
- enabled: (name: string) => boolean;
11
- humanize: (val: string | number, options?: Object) => string | number;
12
- destroy: () => void;
13
- names: any[];
14
- skips: any[];
15
- formatters: {};
16
- selectColor: (namespace: string) => number | string;
17
- };
18
- default: {
19
- (namespace: string): Function;
20
- debug: /*elided*/ any;
21
- default: /*elided*/ any;
22
- coerce: (val: Mixed) => Mixed;
23
- disable: () => string;
24
- enable: (namespaces: string) => void;
25
- enabled: (name: string) => boolean;
26
- humanize: (val: string | number, options?: Object) => string | number;
27
- destroy: () => void;
28
- names: any[];
29
- skips: any[];
30
- formatters: {};
31
- selectColor: (namespace: string) => number | string;
32
- };
33
- coerce: (val: Mixed) => Mixed;
34
- disable: () => string;
35
- enable: (namespaces: string) => void;
36
- enabled: (name: string) => boolean;
37
- humanize: (val: string | number, options?: Object) => string | number;
38
- destroy: (() => void) | (() => void);
39
- names: any[];
40
- skips: any[];
41
- formatters: {};
42
- selectColor: (namespace: string) => number | string;
43
- formatArgs: typeof formatArgs;
44
- save: typeof save;
45
- load: typeof load;
46
- useColors: typeof useColors;
47
- storage: LocalStorage;
48
- /**
49
- * Colors.
50
- */
51
- colors: string[];
52
- /**
53
- * Invokes `console.debug()` when available.
54
- * No-op when `console.debug` is not a "function".
55
- * If `console.debug` is not available, falls back
56
- * to `console.log`.
57
- *
58
- * @api public
59
- */
60
- log: (...data: any[]) => void;
61
- };
62
- export = _exports;
63
- /**
64
- * Colorize log arguments if enabled.
65
- *
66
- * @api public
67
- */
68
- declare function formatArgs(args: any): void;
69
- /**
70
- * Save `namespaces`.
71
- *
72
- * @param {String} namespaces
73
- * @api private
74
- */
75
- declare function save(namespaces: string): void;
76
- /**
77
- * Load `namespaces`.
78
- *
79
- * @return {String} returns the previously persisted debug modes
80
- * @api private
81
- */
82
- declare function load(): string;
83
- /**
84
- * Currently only WebKit-based Web Inspectors, Firefox >= v31,
85
- * and the Firebug extension (any Firefox version) are known
86
- * to support "%c" CSS customizations.
87
- *
88
- * TODO: add a `localStorage` variable to explicitly enable/disable colors
89
- */
90
- declare function useColors(): any;