@devlens/vue 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/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # @devlens/vue
2
+
3
+ DevLens Vue 3 integration -- automatic runtime error detection for Vue applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @devlens/core @devlens/vue
9
+ ```
10
+
11
+ **Peer dependencies:** Vue >= 3.3.0
12
+
13
+ ## Quick Start
14
+
15
+ ```ts
16
+ import { createApp } from 'vue';
17
+ import { createDevLensPlugin } from '@devlens/vue';
18
+
19
+ const app = createApp(App);
20
+
21
+ app.use(createDevLensPlugin({
22
+ enabled: true,
23
+ minSeverity: 'warn',
24
+ }));
25
+
26
+ app.mount('#app');
27
+ ```
28
+
29
+ The plugin automatically installs `app.config.errorHandler` and `app.config.warnHandler` to capture Vue errors and warnings.
30
+
31
+ ## Guarded Ref
32
+
33
+ Reactive ref with null/undefined detection:
34
+
35
+ ```ts
36
+ import { useGuardedRef } from '@devlens/vue';
37
+
38
+ const user = useGuardedRef(initialUser, 'UserProfile');
39
+
40
+ // Accessing null/undefined properties on user.value triggers detection
41
+ ```
42
+
43
+ ## Watch Data
44
+
45
+ Monitor data for null/undefined values:
46
+
47
+ ```ts
48
+ import { useGuardedWatch } from '@devlens/vue';
49
+
50
+ useGuardedWatch({ user, posts, settings }, 'Dashboard');
51
+
52
+ // [RENDER] DevLens [WARN] render-data: "posts" is undefined in Dashboard
53
+ ```
54
+
55
+ ## API Reference
56
+
57
+ | Export | Description |
58
+ |--------|-------------|
59
+ | `createDevLensPlugin(options?)` | Vue 3 plugin with auto error/warn handlers |
60
+ | `useDevLens()` | Inject the engine instance |
61
+ | `useGuardedRef(initialValue, label?)` | Reactive ref with null/undefined detection |
62
+ | `useGuardedWatch(data, label?)` | Watch data for null/undefined |
63
+
64
+ ## Details
65
+
66
+ - ~5KB ESM bundle
67
+ - Auto error handler: `app.config.errorHandler`
68
+ - Auto warn handler: `app.config.warnHandler`
69
+ - Network interceptor and global catcher auto-installed
70
+ - Dual ESM + CJS output
71
+ - Full TypeScript declarations
72
+ - Production-safe -- auto-disabled in production
73
+
74
+ ## License
75
+
76
+ MIT -- [github.com/crashsense/devlens](https://github.com/crashsense/devlens)
@@ -0,0 +1,18 @@
1
+ import { InjectionKey, App, Ref } from 'vue';
2
+ import { DevLensEngine, DevLensConfig } from '@devlens/core';
3
+ export { DetectedIssue, DevLensConfig, IssueCategory, Severity } from '@devlens/core';
4
+
5
+ declare const DevLensKey: InjectionKey<DevLensEngine>;
6
+ interface DevLensPluginOptions extends DevLensConfig {
7
+ }
8
+ declare function createDevLensPlugin(options?: DevLensPluginOptions): {
9
+ install(app: App): void;
10
+ uninstall(): void;
11
+ getEngine(): DevLensEngine | null;
12
+ };
13
+
14
+ declare function useDevLens(): DevLensEngine | null;
15
+ declare function useGuardedRef<T extends object>(initialValue: T, label?: string): Ref<T>;
16
+ declare function useGuardedWatch(data: Record<string, unknown>, label?: string): void;
17
+
18
+ export { DevLensKey, type DevLensPluginOptions, createDevLensPlugin, useDevLens, useGuardedRef, useGuardedWatch };
@@ -0,0 +1,18 @@
1
+ import { InjectionKey, App, Ref } from 'vue';
2
+ import { DevLensEngine, DevLensConfig } from '@devlens/core';
3
+ export { DetectedIssue, DevLensConfig, IssueCategory, Severity } from '@devlens/core';
4
+
5
+ declare const DevLensKey: InjectionKey<DevLensEngine>;
6
+ interface DevLensPluginOptions extends DevLensConfig {
7
+ }
8
+ declare function createDevLensPlugin(options?: DevLensPluginOptions): {
9
+ install(app: App): void;
10
+ uninstall(): void;
11
+ getEngine(): DevLensEngine | null;
12
+ };
13
+
14
+ declare function useDevLens(): DevLensEngine | null;
15
+ declare function useGuardedRef<T extends object>(initialValue: T, label?: string): Ref<T>;
16
+ declare function useGuardedWatch(data: Record<string, unknown>, label?: string): void;
17
+
18
+ export { DevLensKey, type DevLensPluginOptions, createDevLensPlugin, useDevLens, useGuardedRef, useGuardedWatch };
package/dist/index.js ADDED
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ var core = require('@devlens/core');
4
+ var vue = require('vue');
5
+
6
+ // src/plugin.ts
7
+ var DevLensKey = /* @__PURE__ */ Symbol("devlens");
8
+ function isProductionEnv() {
9
+ try {
10
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
11
+ } catch {
12
+ return false;
13
+ }
14
+ }
15
+ function createDevLensPlugin(options = {}) {
16
+ let engine = null;
17
+ const cleanups = [];
18
+ return {
19
+ install(app) {
20
+ if (options.enabled === false || isProductionEnv()) {
21
+ return;
22
+ }
23
+ engine = core.createDetectionEngine(options);
24
+ app.provide(DevLensKey, engine);
25
+ const networkConfig = options.modules?.network === false ? void 0 : options.modules?.network;
26
+ const catcherConfig = options.modules?.catcher === false ? void 0 : options.modules?.catcher;
27
+ if (networkConfig !== void 0 || options.modules?.network !== false) {
28
+ const network = core.createNetworkInterceptor(engine, networkConfig);
29
+ network.install();
30
+ cleanups.push(network);
31
+ }
32
+ if (catcherConfig !== void 0 || options.modules?.catcher !== false) {
33
+ const catcher = core.createGlobalCatcher(engine, catcherConfig);
34
+ catcher.install();
35
+ cleanups.push(catcher);
36
+ }
37
+ app.config.errorHandler = (err, instance, info) => {
38
+ if (!engine?.isEnabled()) return;
39
+ const error = err instanceof Error ? err : new Error(String(err));
40
+ const componentName = instance?.$options?.name ?? instance?.$options?.__name ?? "AnonymousComponent";
41
+ engine.report({
42
+ id: `unhandled-error:vue:${error.message}`,
43
+ timestamp: Date.now(),
44
+ severity: "error",
45
+ category: "unhandled-error",
46
+ message: `Vue error in ${componentName}: ${error.message}`,
47
+ details: {
48
+ component: componentName,
49
+ lifecycleHook: info
50
+ },
51
+ stack: error.stack,
52
+ source: `Vue:${componentName}`,
53
+ suggestion: `Error in ${info} of ${componentName} \u2014 check the component logic`
54
+ });
55
+ };
56
+ app.config.warnHandler = (msg, instance, trace) => {
57
+ if (!engine?.isEnabled()) return;
58
+ const componentName = instance?.$options?.name ?? instance?.$options?.__name ?? "AnonymousComponent";
59
+ engine.report({
60
+ id: `unhandled-error:vue-warn:${msg.slice(0, 80)}`,
61
+ timestamp: Date.now(),
62
+ severity: "warn",
63
+ category: "unhandled-error",
64
+ message: `Vue warning in ${componentName}: ${msg}`,
65
+ details: {
66
+ component: componentName,
67
+ trace
68
+ },
69
+ source: `Vue:${componentName}`,
70
+ suggestion: "Check the Vue warning above \u2014 it may indicate a potential issue"
71
+ });
72
+ };
73
+ },
74
+ uninstall() {
75
+ for (const cleanup of cleanups) {
76
+ cleanup.uninstall();
77
+ }
78
+ cleanups.length = 0;
79
+ engine = null;
80
+ },
81
+ getEngine() {
82
+ return engine;
83
+ }
84
+ };
85
+ }
86
+ function useDevLens() {
87
+ return vue.inject(DevLensKey, null);
88
+ }
89
+ function useGuardedRef(initialValue, label) {
90
+ const engine = useDevLens();
91
+ const source = vue.ref(initialValue);
92
+ if (!engine || !engine.isEnabled()) {
93
+ return source;
94
+ }
95
+ const guardian = core.createDataGuardian(engine);
96
+ const guarded = vue.ref(guardian.guard(source.value, label));
97
+ vue.watch(source, (newVal) => {
98
+ if (newVal === null || newVal === void 0 || typeof newVal !== "object") {
99
+ guarded.value = newVal;
100
+ return;
101
+ }
102
+ const freshGuardian = core.createDataGuardian(engine);
103
+ guarded.value = freshGuardian.guard(newVal, label);
104
+ }, { deep: true });
105
+ return guarded;
106
+ }
107
+ function useGuardedWatch(data, label) {
108
+ const engine = useDevLens();
109
+ if (!engine || !engine.isEnabled()) return;
110
+ const resolvedLabel = label ?? "useGuardedWatch";
111
+ const dataRef = vue.ref(data);
112
+ vue.watch(dataRef, (current) => {
113
+ for (const [key, value] of Object.entries(current)) {
114
+ if (value === null || value === void 0) {
115
+ const issue = {
116
+ id: `render-data:${resolvedLabel}:${key}`,
117
+ timestamp: Date.now(),
118
+ severity: "warn",
119
+ category: "render-data",
120
+ message: `"${key}" is ${value === null ? "null" : "undefined"} in ${resolvedLabel}`,
121
+ path: `${resolvedLabel}.${key}`,
122
+ foundValue: value,
123
+ expectedType: "non-nullish value",
124
+ source: resolvedLabel,
125
+ suggestion: `"${key}" is ${value === null ? "null" : "undefined"} \u2014 check data loading in ${resolvedLabel}`
126
+ };
127
+ engine.report(issue);
128
+ }
129
+ }
130
+ }, { immediate: true, deep: true });
131
+ }
132
+
133
+ exports.DevLensKey = DevLensKey;
134
+ exports.createDevLensPlugin = createDevLensPlugin;
135
+ exports.useDevLens = useDevLens;
136
+ exports.useGuardedRef = useGuardedRef;
137
+ exports.useGuardedWatch = useGuardedWatch;
138
+ //# sourceMappingURL=index.js.map
139
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/composables.ts"],"names":["createDetectionEngine","createNetworkInterceptor","createGlobalCatcher","inject","ref","createDataGuardian","watch"],"mappings":"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","file":"index.js","sourcesContent":["import type { App, InjectionKey } from 'vue';\nimport type { DevLensConfig, DevLensEngine } from '@devlens/core';\nimport {\n createDetectionEngine,\n createNetworkInterceptor,\n createGlobalCatcher,\n} from '@devlens/core';\n\nexport const DevLensKey: InjectionKey<DevLensEngine> = Symbol('devlens');\n\nfunction isProductionEnv(): boolean {\n try {\n return (\n typeof process !== 'undefined' &&\n process.env?.NODE_ENV === 'production'\n );\n } catch {\n return false;\n }\n}\n\nexport interface DevLensPluginOptions extends DevLensConfig {}\n\nexport function createDevLensPlugin(options: DevLensPluginOptions = {}) {\n let engine: DevLensEngine | null = null;\n const cleanups: Array<{ uninstall(): void }> = [];\n\n return {\n install(app: App): void {\n if (options.enabled === false || isProductionEnv()) {\n return;\n }\n\n engine = createDetectionEngine(options);\n app.provide(DevLensKey, engine);\n\n const networkConfig =\n options.modules?.network === false ? undefined : options.modules?.network;\n const catcherConfig =\n options.modules?.catcher === false ? undefined : options.modules?.catcher;\n\n if (networkConfig !== undefined || options.modules?.network !== false) {\n const network = createNetworkInterceptor(engine, networkConfig);\n network.install();\n cleanups.push(network);\n }\n\n if (catcherConfig !== undefined || options.modules?.catcher !== false) {\n const catcher = createGlobalCatcher(engine, catcherConfig);\n catcher.install();\n cleanups.push(catcher);\n }\n\n app.config.errorHandler = (err, instance, info) => {\n if (!engine?.isEnabled()) return;\n\n const error = err instanceof Error ? err : new Error(String(err));\n const componentName =\n (instance?.$options?.name) ??\n (instance?.$options?.__name) ??\n 'AnonymousComponent';\n\n engine.report({\n id: `unhandled-error:vue:${error.message}`,\n timestamp: Date.now(),\n severity: 'error',\n category: 'unhandled-error',\n message: `Vue error in ${componentName}: ${error.message}`,\n details: {\n component: componentName,\n lifecycleHook: info,\n },\n stack: error.stack,\n source: `Vue:${componentName}`,\n suggestion: `Error in ${info} of ${componentName} — check the component logic`,\n });\n };\n\n app.config.warnHandler = (msg, instance, trace) => {\n if (!engine?.isEnabled()) return;\n\n const componentName =\n (instance?.$options?.name) ??\n (instance?.$options?.__name) ??\n 'AnonymousComponent';\n\n engine.report({\n id: `unhandled-error:vue-warn:${msg.slice(0, 80)}`,\n timestamp: Date.now(),\n severity: 'warn',\n category: 'unhandled-error',\n message: `Vue warning in ${componentName}: ${msg}`,\n details: {\n component: componentName,\n trace,\n },\n source: `Vue:${componentName}`,\n suggestion: 'Check the Vue warning above — it may indicate a potential issue',\n });\n };\n },\n\n uninstall(): void {\n for (const cleanup of cleanups) {\n cleanup.uninstall();\n }\n cleanups.length = 0;\n engine = null;\n },\n\n getEngine(): DevLensEngine | null {\n return engine;\n },\n };\n}\n","import { inject, ref, watch, type Ref } from 'vue';\nimport type { DevLensEngine, DetectedIssue } from '@devlens/core';\nimport { createDataGuardian } from '@devlens/core';\nimport { DevLensKey } from './plugin';\n\nexport function useDevLens(): DevLensEngine | null {\n return inject(DevLensKey, null);\n}\n\nexport function useGuardedRef<T extends object>(\n initialValue: T,\n label?: string,\n): Ref<T> {\n const engine = useDevLens();\n const source = ref(initialValue) as Ref<T>;\n\n if (!engine || !engine.isEnabled()) {\n return source;\n }\n\n const guardian = createDataGuardian(engine);\n const guarded = ref(guardian.guard(source.value, label)) as Ref<T>;\n\n watch(source, (newVal) => {\n if (newVal === null || newVal === undefined || typeof newVal !== 'object') {\n guarded.value = newVal;\n return;\n }\n const freshGuardian = createDataGuardian(engine);\n guarded.value = freshGuardian.guard(newVal, label);\n }, { deep: true });\n\n return guarded;\n}\n\nexport function useGuardedWatch(\n data: Record<string, unknown>,\n label?: string,\n): void {\n const engine = useDevLens();\n if (!engine || !engine.isEnabled()) return;\n\n const resolvedLabel = label ?? 'useGuardedWatch';\n\n const dataRef = ref(data);\n\n watch(dataRef, (current) => {\n for (const [key, value] of Object.entries(current)) {\n if (value === null || value === undefined) {\n const issue: DetectedIssue = {\n id: `render-data:${resolvedLabel}:${key}`,\n timestamp: Date.now(),\n severity: 'warn',\n category: 'render-data',\n message: `\"${key}\" is ${value === null ? 'null' : 'undefined'} in ${resolvedLabel}`,\n path: `${resolvedLabel}.${key}`,\n foundValue: value,\n expectedType: 'non-nullish value',\n source: resolvedLabel,\n suggestion: `\"${key}\" is ${value === null ? 'null' : 'undefined'} — check data loading in ${resolvedLabel}`,\n };\n engine.report(issue);\n }\n }\n }, { immediate: true, deep: true });\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,133 @@
1
+ import { createDetectionEngine, createNetworkInterceptor, createGlobalCatcher, createDataGuardian } from '@devlens/core';
2
+ import { inject, ref, watch } from 'vue';
3
+
4
+ // src/plugin.ts
5
+ var DevLensKey = /* @__PURE__ */ Symbol("devlens");
6
+ function isProductionEnv() {
7
+ try {
8
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
13
+ function createDevLensPlugin(options = {}) {
14
+ let engine = null;
15
+ const cleanups = [];
16
+ return {
17
+ install(app) {
18
+ if (options.enabled === false || isProductionEnv()) {
19
+ return;
20
+ }
21
+ engine = createDetectionEngine(options);
22
+ app.provide(DevLensKey, engine);
23
+ const networkConfig = options.modules?.network === false ? void 0 : options.modules?.network;
24
+ const catcherConfig = options.modules?.catcher === false ? void 0 : options.modules?.catcher;
25
+ if (networkConfig !== void 0 || options.modules?.network !== false) {
26
+ const network = createNetworkInterceptor(engine, networkConfig);
27
+ network.install();
28
+ cleanups.push(network);
29
+ }
30
+ if (catcherConfig !== void 0 || options.modules?.catcher !== false) {
31
+ const catcher = createGlobalCatcher(engine, catcherConfig);
32
+ catcher.install();
33
+ cleanups.push(catcher);
34
+ }
35
+ app.config.errorHandler = (err, instance, info) => {
36
+ if (!engine?.isEnabled()) return;
37
+ const error = err instanceof Error ? err : new Error(String(err));
38
+ const componentName = instance?.$options?.name ?? instance?.$options?.__name ?? "AnonymousComponent";
39
+ engine.report({
40
+ id: `unhandled-error:vue:${error.message}`,
41
+ timestamp: Date.now(),
42
+ severity: "error",
43
+ category: "unhandled-error",
44
+ message: `Vue error in ${componentName}: ${error.message}`,
45
+ details: {
46
+ component: componentName,
47
+ lifecycleHook: info
48
+ },
49
+ stack: error.stack,
50
+ source: `Vue:${componentName}`,
51
+ suggestion: `Error in ${info} of ${componentName} \u2014 check the component logic`
52
+ });
53
+ };
54
+ app.config.warnHandler = (msg, instance, trace) => {
55
+ if (!engine?.isEnabled()) return;
56
+ const componentName = instance?.$options?.name ?? instance?.$options?.__name ?? "AnonymousComponent";
57
+ engine.report({
58
+ id: `unhandled-error:vue-warn:${msg.slice(0, 80)}`,
59
+ timestamp: Date.now(),
60
+ severity: "warn",
61
+ category: "unhandled-error",
62
+ message: `Vue warning in ${componentName}: ${msg}`,
63
+ details: {
64
+ component: componentName,
65
+ trace
66
+ },
67
+ source: `Vue:${componentName}`,
68
+ suggestion: "Check the Vue warning above \u2014 it may indicate a potential issue"
69
+ });
70
+ };
71
+ },
72
+ uninstall() {
73
+ for (const cleanup of cleanups) {
74
+ cleanup.uninstall();
75
+ }
76
+ cleanups.length = 0;
77
+ engine = null;
78
+ },
79
+ getEngine() {
80
+ return engine;
81
+ }
82
+ };
83
+ }
84
+ function useDevLens() {
85
+ return inject(DevLensKey, null);
86
+ }
87
+ function useGuardedRef(initialValue, label) {
88
+ const engine = useDevLens();
89
+ const source = ref(initialValue);
90
+ if (!engine || !engine.isEnabled()) {
91
+ return source;
92
+ }
93
+ const guardian = createDataGuardian(engine);
94
+ const guarded = ref(guardian.guard(source.value, label));
95
+ watch(source, (newVal) => {
96
+ if (newVal === null || newVal === void 0 || typeof newVal !== "object") {
97
+ guarded.value = newVal;
98
+ return;
99
+ }
100
+ const freshGuardian = createDataGuardian(engine);
101
+ guarded.value = freshGuardian.guard(newVal, label);
102
+ }, { deep: true });
103
+ return guarded;
104
+ }
105
+ function useGuardedWatch(data, label) {
106
+ const engine = useDevLens();
107
+ if (!engine || !engine.isEnabled()) return;
108
+ const resolvedLabel = label ?? "useGuardedWatch";
109
+ const dataRef = ref(data);
110
+ watch(dataRef, (current) => {
111
+ for (const [key, value] of Object.entries(current)) {
112
+ if (value === null || value === void 0) {
113
+ const issue = {
114
+ id: `render-data:${resolvedLabel}:${key}`,
115
+ timestamp: Date.now(),
116
+ severity: "warn",
117
+ category: "render-data",
118
+ message: `"${key}" is ${value === null ? "null" : "undefined"} in ${resolvedLabel}`,
119
+ path: `${resolvedLabel}.${key}`,
120
+ foundValue: value,
121
+ expectedType: "non-nullish value",
122
+ source: resolvedLabel,
123
+ suggestion: `"${key}" is ${value === null ? "null" : "undefined"} \u2014 check data loading in ${resolvedLabel}`
124
+ };
125
+ engine.report(issue);
126
+ }
127
+ }
128
+ }, { immediate: true, deep: true });
129
+ }
130
+
131
+ export { DevLensKey, createDevLensPlugin, useDevLens, useGuardedRef, useGuardedWatch };
132
+ //# sourceMappingURL=index.mjs.map
133
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/composables.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { App, InjectionKey } from 'vue';\nimport type { DevLensConfig, DevLensEngine } from '@devlens/core';\nimport {\n createDetectionEngine,\n createNetworkInterceptor,\n createGlobalCatcher,\n} from '@devlens/core';\n\nexport const DevLensKey: InjectionKey<DevLensEngine> = Symbol('devlens');\n\nfunction isProductionEnv(): boolean {\n try {\n return (\n typeof process !== 'undefined' &&\n process.env?.NODE_ENV === 'production'\n );\n } catch {\n return false;\n }\n}\n\nexport interface DevLensPluginOptions extends DevLensConfig {}\n\nexport function createDevLensPlugin(options: DevLensPluginOptions = {}) {\n let engine: DevLensEngine | null = null;\n const cleanups: Array<{ uninstall(): void }> = [];\n\n return {\n install(app: App): void {\n if (options.enabled === false || isProductionEnv()) {\n return;\n }\n\n engine = createDetectionEngine(options);\n app.provide(DevLensKey, engine);\n\n const networkConfig =\n options.modules?.network === false ? undefined : options.modules?.network;\n const catcherConfig =\n options.modules?.catcher === false ? undefined : options.modules?.catcher;\n\n if (networkConfig !== undefined || options.modules?.network !== false) {\n const network = createNetworkInterceptor(engine, networkConfig);\n network.install();\n cleanups.push(network);\n }\n\n if (catcherConfig !== undefined || options.modules?.catcher !== false) {\n const catcher = createGlobalCatcher(engine, catcherConfig);\n catcher.install();\n cleanups.push(catcher);\n }\n\n app.config.errorHandler = (err, instance, info) => {\n if (!engine?.isEnabled()) return;\n\n const error = err instanceof Error ? err : new Error(String(err));\n const componentName =\n (instance?.$options?.name) ??\n (instance?.$options?.__name) ??\n 'AnonymousComponent';\n\n engine.report({\n id: `unhandled-error:vue:${error.message}`,\n timestamp: Date.now(),\n severity: 'error',\n category: 'unhandled-error',\n message: `Vue error in ${componentName}: ${error.message}`,\n details: {\n component: componentName,\n lifecycleHook: info,\n },\n stack: error.stack,\n source: `Vue:${componentName}`,\n suggestion: `Error in ${info} of ${componentName} — check the component logic`,\n });\n };\n\n app.config.warnHandler = (msg, instance, trace) => {\n if (!engine?.isEnabled()) return;\n\n const componentName =\n (instance?.$options?.name) ??\n (instance?.$options?.__name) ??\n 'AnonymousComponent';\n\n engine.report({\n id: `unhandled-error:vue-warn:${msg.slice(0, 80)}`,\n timestamp: Date.now(),\n severity: 'warn',\n category: 'unhandled-error',\n message: `Vue warning in ${componentName}: ${msg}`,\n details: {\n component: componentName,\n trace,\n },\n source: `Vue:${componentName}`,\n suggestion: 'Check the Vue warning above — it may indicate a potential issue',\n });\n };\n },\n\n uninstall(): void {\n for (const cleanup of cleanups) {\n cleanup.uninstall();\n }\n cleanups.length = 0;\n engine = null;\n },\n\n getEngine(): DevLensEngine | null {\n return engine;\n },\n };\n}\n","import { inject, ref, watch, type Ref } from 'vue';\nimport type { DevLensEngine, DetectedIssue } from '@devlens/core';\nimport { createDataGuardian } from '@devlens/core';\nimport { DevLensKey } from './plugin';\n\nexport function useDevLens(): DevLensEngine | null {\n return inject(DevLensKey, null);\n}\n\nexport function useGuardedRef<T extends object>(\n initialValue: T,\n label?: string,\n): Ref<T> {\n const engine = useDevLens();\n const source = ref(initialValue) as Ref<T>;\n\n if (!engine || !engine.isEnabled()) {\n return source;\n }\n\n const guardian = createDataGuardian(engine);\n const guarded = ref(guardian.guard(source.value, label)) as Ref<T>;\n\n watch(source, (newVal) => {\n if (newVal === null || newVal === undefined || typeof newVal !== 'object') {\n guarded.value = newVal;\n return;\n }\n const freshGuardian = createDataGuardian(engine);\n guarded.value = freshGuardian.guard(newVal, label);\n }, { deep: true });\n\n return guarded;\n}\n\nexport function useGuardedWatch(\n data: Record<string, unknown>,\n label?: string,\n): void {\n const engine = useDevLens();\n if (!engine || !engine.isEnabled()) return;\n\n const resolvedLabel = label ?? 'useGuardedWatch';\n\n const dataRef = ref(data);\n\n watch(dataRef, (current) => {\n for (const [key, value] of Object.entries(current)) {\n if (value === null || value === undefined) {\n const issue: DetectedIssue = {\n id: `render-data:${resolvedLabel}:${key}`,\n timestamp: Date.now(),\n severity: 'warn',\n category: 'render-data',\n message: `\"${key}\" is ${value === null ? 'null' : 'undefined'} in ${resolvedLabel}`,\n path: `${resolvedLabel}.${key}`,\n foundValue: value,\n expectedType: 'non-nullish value',\n source: resolvedLabel,\n suggestion: `\"${key}\" is ${value === null ? 'null' : 'undefined'} — check data loading in ${resolvedLabel}`,\n };\n engine.report(issue);\n }\n }\n }, { immediate: true, deep: true });\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@devlens/vue",
3
+ "version": "1.0.0",
4
+ "description": "DevLens Vue integration - automatic error detection for Vue apps",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "sideEffects": false,
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "test": "vitest run",
28
+ "clean": "rm -rf dist",
29
+ "typecheck": "tsc --noEmit"
30
+ },
31
+ "keywords": [
32
+ "devlens",
33
+ "crashsense",
34
+ "vue",
35
+ "debug",
36
+ "error-detection",
37
+ "developer-tools"
38
+ ],
39
+ "author": "crashsense",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/crashsense/devlens.git",
43
+ "directory": "packages/vue"
44
+ },
45
+ "homepage": "https://github.com/crashsense/devlens#readme",
46
+ "bugs": {
47
+ "url": "https://github.com/crashsense/devlens/issues"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "license": "MIT",
53
+ "peerDependencies": {
54
+ "vue": ">=3.3.0"
55
+ },
56
+ "dependencies": {
57
+ "@devlens/core": "2.0.0"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^25.3.0",
61
+ "tsup": "^8.4.0",
62
+ "vitest": "^3.0.0",
63
+ "vue": "^3.5.0"
64
+ }
65
+ }