@vingy/vuebugger 0.1.2 → 0.3.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/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ComponentInternalInstance, Plugin } from "vue";
2
2
 
3
- //#region node_modules/.pnpm/hookable@6.0.1/node_modules/hookable/dist/index.d.mts
3
+ //#region ../../node_modules/.pnpm/hookable@6.0.1/node_modules/hookable/dist/index.d.mts
4
4
  type CreateTask = (name?: string) => {
5
5
  run: (function_: () => Promise<any> | any) => Promise<any> | any;
6
6
  };
@@ -19,11 +19,14 @@ type VuebuggerEntry = {
19
19
  componentInstance: ComponentInternalInstance | null;
20
20
  debugState: Record<string, any>;
21
21
  };
22
+ type PluginOptions = {
23
+ uidFn?: () => string;
24
+ };
22
25
  //#endregion
23
26
  //#region src/debug.d.ts
24
- declare function debug<T extends Record<string, any>>(groupId: VuebuggerEntry['groupId'], state: T): T;
27
+ declare const debug: <T extends Record<string, any>>(groupId: VuebuggerEntry["groupId"], state: T) => T;
25
28
  //#endregion
26
29
  //#region src/index.d.ts
27
- declare const plugin$1: Plugin<any[], any[]>;
30
+ declare const plugin$1: Plugin<PluginOptions | undefined>;
28
31
  //#endregion
29
32
  export { plugin$1 as DebugPlugin, plugin$1 as default, debug };
package/dist/index.mjs CHANGED
@@ -1,6 +1,69 @@
1
- import { getCurrentInstance, getCurrentScope, onBeforeUnmount, toValue, watch } from "vue";
1
+ import { effectScope, getCurrentInstance, getCurrentScope, isReadonly, onScopeDispose, toValue, watch } from "vue";
2
2
 
3
- //#region node_modules/.pnpm/@vue+devtools-shared@8.0.5/node_modules/@vue/devtools-shared/dist/index.js
3
+ //#region src/registry.ts
4
+ const byUid = /* @__PURE__ */ new Map();
5
+ const byGroupId = /* @__PURE__ */ new Map();
6
+ const callbacks = [];
7
+ const runCallbacks = (entry) => callbacks.forEach((cb) => cb(entry));
8
+ const withCallbacks = (fn) => (entry) => {
9
+ fn(entry);
10
+ runCallbacks(entry);
11
+ };
12
+ const upsert = withCallbacks((entry) => {
13
+ const { uid, groupId } = entry;
14
+ byUid.set(uid, entry);
15
+ const group = byGroupId.get(groupId);
16
+ if (!group) byGroupId.set(groupId, new Set([uid]));
17
+ else group.add(uid);
18
+ });
19
+ const remove = withCallbacks((entry) => {
20
+ const { uid, groupId } = entry;
21
+ byUid.delete(uid);
22
+ const group = byGroupId.get(groupId);
23
+ group?.delete(uid);
24
+ if (group?.size === 0) byGroupId.delete(groupId);
25
+ });
26
+ const onUpdate = (fn) => {
27
+ callbacks.push(fn);
28
+ };
29
+
30
+ //#endregion
31
+ //#region src/debug.ts
32
+ let getUid = () => Math.random().toString(36).slice(2, 9);
33
+ const setUidGenerator = (fn) => {
34
+ getUid = fn;
35
+ };
36
+ const debug = (groupId, state) => {
37
+ if (!import.meta.env.DEV) return state;
38
+ const instance = getCurrentInstance();
39
+ const componentName = instance?.type.name || instance?.type.__name || "No component";
40
+ const uid = `${componentName}/${groupId}-${getUid()}`;
41
+ (getCurrentScope() ?? effectScope()).run(() => {
42
+ onScopeDispose(() => remove({
43
+ groupId,
44
+ uid,
45
+ componentName,
46
+ componentInstance: instance,
47
+ debugState: state
48
+ }));
49
+ watch(() => state, (value, _) => {
50
+ upsert({
51
+ groupId,
52
+ uid,
53
+ componentName,
54
+ componentInstance: instance,
55
+ debugState: value
56
+ });
57
+ }, {
58
+ immediate: true,
59
+ deep: true
60
+ });
61
+ });
62
+ return state;
63
+ };
64
+
65
+ //#endregion
66
+ //#region ../../node_modules/.pnpm/@vue+devtools-shared@8.0.5/node_modules/@vue/devtools-shared/dist/index.js
4
67
  var __create$1 = Object.create;
5
68
  var __defProp$1 = Object.defineProperty;
6
69
  var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
@@ -188,7 +251,7 @@ function basename(filename, ext) {
188
251
  const deepClone = (0, import_rfdc.default)({ circles: true });
189
252
 
190
253
  //#endregion
191
- //#region node_modules/.pnpm/perfect-debounce@2.1.0/node_modules/perfect-debounce/dist/index.mjs
254
+ //#region ../../node_modules/.pnpm/perfect-debounce@2.1.0/node_modules/perfect-debounce/dist/index.mjs
192
255
  const DEBOUNCE_DEFAULTS = { trailing: true };
193
256
  /**
194
257
  Debounce functions
@@ -276,7 +339,7 @@ async function _applyPromised(fn, _this, args) {
276
339
  }
277
340
 
278
341
  //#endregion
279
- //#region node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs
342
+ //#region ../../node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs
280
343
  function flatHooks(configHooks, hooks = {}, parentName) {
281
344
  for (const key in configHooks) {
282
345
  const subHook = configHooks[key];
@@ -433,7 +496,7 @@ function createHooks() {
433
496
  }
434
497
 
435
498
  //#endregion
436
- //#region node_modules/.pnpm/@vue+devtools-kit@8.0.5/node_modules/@vue/devtools-kit/dist/index.js
499
+ //#region ../../node_modules/.pnpm/@vue+devtools-kit@8.0.5/node_modules/@vue/devtools-kit/dist/index.js
437
500
  var __create = Object.create;
438
501
  var __defProp = Object.defineProperty;
439
502
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -837,14 +900,14 @@ let ReactiveFlags = /* @__PURE__ */ function(ReactiveFlags$1) {
837
900
  /**
838
901
  * @from [@vue/reactivity](https://github.com/vuejs/core/blob/1c3327a0fa5983aa9078e3f7bb2330f572435425/packages/reactivity/src/reactive.ts#L330-L332)
839
902
  */
840
- function isReadonly(value) {
903
+ function isReadonly$1(value) {
841
904
  return !!(value && value[ReactiveFlags.IS_READONLY]);
842
905
  }
843
906
  /**
844
907
  * @from [@vue/reactivity](https://github.com/vuejs/core/blob/1c3327a0fa5983aa9078e3f7bb2330f572435425/packages/reactivity/src/reactive.ts#L312-L317)
845
908
  */
846
909
  function isReactive$1(value) {
847
- if (isReadonly(value)) return isReactive$1(value[ReactiveFlags.RAW]);
910
+ if (isReadonly$1(value)) return isReactive$1(value[ReactiveFlags.RAW]);
848
911
  return !!(value && value[ReactiveFlags.IS_REACTIVE]);
849
912
  }
850
913
  function isRef$1(r) {
@@ -3780,39 +3843,12 @@ target.__VUE_DEVTOOLS_KIT_BROADCAST_RPC_SERVER__ ??= null;
3780
3843
  const MAX_SERIALIZED_SIZE = 2 * 1024 * 1024;
3781
3844
 
3782
3845
  //#endregion
3783
- //#region src/registry.ts
3784
- const byUid = /* @__PURE__ */ new Map();
3785
- const byGroupId = /* @__PURE__ */ new Map();
3786
- const callbacks = [];
3787
- const runCallbacks = (entry) => callbacks.forEach((cb) => cb(entry));
3788
- const withCallbacks = (fn) => (entry) => {
3789
- fn(entry);
3790
- runCallbacks(entry);
3791
- };
3792
- const upsert = withCallbacks((entry) => {
3793
- const { uid, groupId } = entry;
3794
- byUid.set(uid, entry);
3795
- const group = byGroupId.get(groupId);
3796
- if (!group) byGroupId.set(groupId, new Set([uid]));
3797
- else group.add(uid);
3798
- console.log("upsert");
3799
- });
3800
- const remove = withCallbacks((entry) => {
3801
- const { uid, groupId } = entry;
3802
- byUid.delete(uid);
3803
- const group = byGroupId.get(groupId);
3804
- group?.delete(uid);
3805
- if (group?.size === 0) byGroupId.delete(groupId);
3806
- console.log("remove");
3807
- });
3808
- const onUpdate = (fn) => {
3809
- callbacks.push(fn);
3810
- };
3846
+ //#region src/constants.ts
3847
+ const INSPECTOR_ID = "vuebugger-inspector";
3848
+ const TIMELINE_ID = "vuebugger-timeline";
3811
3849
 
3812
3850
  //#endregion
3813
3851
  //#region src/devtools.ts
3814
- const INSPECTOR_ID = "vuebugger-inspector";
3815
- const TIMELINE_ID = "vuebugger-timeline";
3816
3852
  const handleGetInspectorTree = (payload) => {
3817
3853
  if (payload.inspectorId === INSPECTOR_ID) {
3818
3854
  const term = payload.filter;
@@ -3845,8 +3881,8 @@ const handleGetInspectorState = (api) => (payload) => {
3845
3881
  if (entry) {
3846
3882
  payload.state = { [payload.nodeId]: Object.entries(entry.debugState).map(([key, value]) => ({
3847
3883
  key,
3848
- value: toValue(value),
3849
- editable: true
3884
+ value,
3885
+ editable: !isReadonly(value)
3850
3886
  })) };
3851
3887
  if (entry.componentInstance) api.highlightElement(entry.componentInstance);
3852
3888
  }
@@ -3857,12 +3893,20 @@ const handleInspectComponent = (payload) => {
3857
3893
  return Object.entries(entry.debugState).map(([key, value]) => ({
3858
3894
  type: entry.uid,
3859
3895
  key,
3860
- value: toValue(value),
3861
- editable: true
3896
+ value,
3897
+ editable: false
3862
3898
  }));
3863
3899
  }).toArray();
3864
3900
  payload.instanceData.state.push(...entries);
3865
3901
  };
3902
+ const handleEditInspectorState = (payload) => {
3903
+ if (payload.inspectorId === INSPECTOR_ID) {
3904
+ const uid = payload.nodeId;
3905
+ const entry = byUid.get(uid);
3906
+ if (!entry) return;
3907
+ payload.set(entry.debugState);
3908
+ }
3909
+ };
3866
3910
  function setupComposableDevtools(app) {
3867
3911
  console.log("🐞 Vuebugger ready to use");
3868
3912
  setupDevToolsPlugin({
@@ -3892,52 +3936,22 @@ function setupComposableDevtools(app) {
3892
3936
  time: api.now(),
3893
3937
  data: entry,
3894
3938
  title: `${entry.uid} state change`,
3895
- groupId: entry.uid,
3896
- meta: { vin: "was here" }
3939
+ groupId: entry.uid
3897
3940
  }
3898
3941
  });
3899
3942
  });
3900
3943
  api.on.getInspectorTree(handleGetInspectorTree);
3901
3944
  api.on.getInspectorState(handleGetInspectorState(api));
3902
3945
  api.on.inspectComponent(handleInspectComponent);
3946
+ api.on.editInspectorState(handleEditInspectorState);
3903
3947
  });
3904
3948
  }
3905
3949
 
3906
- //#endregion
3907
- //#region src/debug.ts
3908
- function debug(groupId, state) {
3909
- if (!import.meta.env.DEV) return state;
3910
- const instance = getCurrentInstance();
3911
- const componentName = instance?.type.name || instance?.type.__name || "No component";
3912
- const uid = `${componentName}/${groupId}-${Math.random().toString(36).slice(2, 9)}`;
3913
- getCurrentScope()?.run(() => {
3914
- onBeforeUnmount(() => remove({
3915
- groupId,
3916
- uid,
3917
- componentName,
3918
- componentInstance: instance,
3919
- debugState: state
3920
- }));
3921
- watch(() => state, (value, _) => {
3922
- upsert({
3923
- groupId,
3924
- uid,
3925
- componentName,
3926
- componentInstance: instance,
3927
- debugState: value
3928
- });
3929
- }, {
3930
- immediate: true,
3931
- deep: true
3932
- });
3933
- });
3934
- return state;
3935
- }
3936
-
3937
3950
  //#endregion
3938
3951
  //#region src/index.ts
3939
- const plugin = { install: (app) => {
3952
+ const plugin = { install: (app, options) => {
3940
3953
  if (!import.meta.env.DEV) return;
3954
+ if (options?.uidFn) setUidGenerator(options.uidFn);
3941
3955
  setupComposableDevtools(app);
3942
3956
  } };
3943
3957
  var src_default = plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vingy/vuebugger",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Vue devtools plugin to debug anything.",
5
5
  "keywords": [
6
6
  "composable",
@@ -34,19 +34,14 @@
34
34
  "access": "public"
35
35
  },
36
36
  "devDependencies": {
37
- "@types/node": "^25.0.10",
38
- "@vue/devtools-api": "^8.0.5",
39
- "oxfmt": "^0.27.0",
40
- "oxlint": "^1.42.0",
41
- "tsdown": "^0.20.1",
42
- "typescript": "^5.9.3",
43
- "vitest": "^4.0.18"
37
+ "@vue/devtools-api": "^8.0.5"
44
38
  },
45
39
  "peerDependencies": {
46
40
  "vue": "^3.5.0"
47
41
  },
48
42
  "scripts": {
49
43
  "test": "vitest",
44
+ "test:ci": "vitest run --coverage",
50
45
  "build": "tsdown",
51
46
  "dev": "tsdown -w"
52
47
  }
package/README.md DELETED
@@ -1,48 +0,0 @@
1
- # Vuebugger
2
-
3
- Vue devtools provide an easy way to inspect component state. But when having something like a composable, you actually need to catch all the returned values in order for them to show up in the devtools. This is where this package can come in handy.
4
-
5
- ## Features
6
-
7
- - Debug composables and reactive state easily
8
- - Tree-shakable with zero runtime overhead
9
- - Simple API: just call `debug(name, state)`
10
-
11
- ## Quick start
12
-
13
- ```bash
14
- pnpm add -D @vingy/vuebugger
15
- ```
16
-
17
- Register the plugin in your app:
18
-
19
- ```ts
20
- import Vuebugger from '@vingy/vuebugger'
21
-
22
- createApp(App).use(Vuebugger)
23
- ```
24
-
25
- ## Usage
26
-
27
- `debug()` registers values from composables so they show up in Vue Devtools.
28
-
29
- ```ts
30
- import { debug } from '@vingy/vuebugger'
31
-
32
- export const useFoo = (initial: number) => {
33
- const multiplier = ref(1) // not easy to debug if something goes wrong
34
-
35
- const inc = () => multiplier.value++
36
- const dec = () => multiplier.value--
37
-
38
- const value = computed(() => initial * multiplier)
39
-
40
- debug('useFoo', { multiplier }) // now visible in devtools
41
-
42
- return { value, inc, dec }
43
- }
44
- ```
45
-
46
- See the demo app in [demo/](demo).
47
-
48
- > **Note:** This plugin is tree-shakable and has zero runtime overhead when `debug()` calls are not used.