@allstak/vue 0.1.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/CHANGELOG.md +48 -0
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/index.d.mts +228 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.js +317 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +249 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +72 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var js = require('@allstak/js');
|
|
4
|
+
var vue = require('vue');
|
|
5
|
+
|
|
6
|
+
// src/init.ts
|
|
7
|
+
function init(config) {
|
|
8
|
+
return js.AllStak.init({
|
|
9
|
+
...config,
|
|
10
|
+
sdkName: config.sdkName ?? "allstak-vue",
|
|
11
|
+
sdkVersion: config.sdkVersion ?? "0.1.0"
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
var DEFAULT_HOOKS = ["mount"];
|
|
15
|
+
var OP_PREFIX = "ui.vue";
|
|
16
|
+
var HOOK_PAIRS = {
|
|
17
|
+
mount: ["beforeMount", "mounted"],
|
|
18
|
+
update: ["beforeUpdate", "updated"],
|
|
19
|
+
unmount: ["beforeUnmount", "unmounted"]
|
|
20
|
+
};
|
|
21
|
+
function componentName(vm) {
|
|
22
|
+
const opts = vm.$options ?? {};
|
|
23
|
+
const internal = vm.$?.type ?? {};
|
|
24
|
+
const name = opts.name ?? opts.__name ?? opts._componentTag ?? internal.name ?? internal.__name;
|
|
25
|
+
return name ? String(name) : "Anonymous Component";
|
|
26
|
+
}
|
|
27
|
+
function shouldTrack(name, trackComponents) {
|
|
28
|
+
if (trackComponents === true) return true;
|
|
29
|
+
if (Array.isArray(trackComponents)) return trackComponents.includes(name);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
function createTracingMixins(options = {}) {
|
|
33
|
+
const trackComponents = options.trackComponents ?? false;
|
|
34
|
+
const hooks = options.hooks ?? DEFAULT_HOOKS;
|
|
35
|
+
const opPrefix = options.opPrefix ?? OP_PREFIX;
|
|
36
|
+
const mixin = {};
|
|
37
|
+
const SPAN_KEY = "__allstak_spans__";
|
|
38
|
+
for (const op of hooks) {
|
|
39
|
+
const pair = HOOK_PAIRS[op];
|
|
40
|
+
if (!pair) continue;
|
|
41
|
+
const [before, after] = pair;
|
|
42
|
+
mixin[before] = function() {
|
|
43
|
+
const name = componentName(this);
|
|
44
|
+
if (!shouldTrack(name, trackComponents)) return;
|
|
45
|
+
try {
|
|
46
|
+
const span = js.AllStak.startSpan(`${opPrefix}.${op}`, {
|
|
47
|
+
op: `${opPrefix}.${op}`,
|
|
48
|
+
description: `Vue ${name}`,
|
|
49
|
+
attributes: {
|
|
50
|
+
"allstak.origin": "auto.ui.vue",
|
|
51
|
+
"vue.component": name,
|
|
52
|
+
"vue.operation": op
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const self = this;
|
|
56
|
+
const bag = self[SPAN_KEY] ?? (self[SPAN_KEY] = {});
|
|
57
|
+
bag[op] = span;
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
mixin[after] = function() {
|
|
62
|
+
try {
|
|
63
|
+
const self = this;
|
|
64
|
+
const bag = self[SPAN_KEY];
|
|
65
|
+
const span = bag?.[op];
|
|
66
|
+
if (span) {
|
|
67
|
+
span.finish("ok");
|
|
68
|
+
delete bag[op];
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return mixin;
|
|
75
|
+
}
|
|
76
|
+
function installComponentTracing(app, options = {}) {
|
|
77
|
+
const trackComponents = options.trackComponents ?? false;
|
|
78
|
+
if (trackComponents === false) return;
|
|
79
|
+
if (Array.isArray(trackComponents) && trackComponents.length === 0) return;
|
|
80
|
+
app.mixin(createTracingMixins(options));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/plugin.ts
|
|
84
|
+
var AllStakPlugin = {
|
|
85
|
+
install(app, options = {}) {
|
|
86
|
+
const {
|
|
87
|
+
attachErrorHandler = true,
|
|
88
|
+
attachWarnHandler = false,
|
|
89
|
+
skipInit = false,
|
|
90
|
+
tracingOptions,
|
|
91
|
+
...config
|
|
92
|
+
} = options;
|
|
93
|
+
if (!skipInit) {
|
|
94
|
+
init(config);
|
|
95
|
+
}
|
|
96
|
+
if (tracingOptions) {
|
|
97
|
+
installComponentTracing(app, tracingOptions);
|
|
98
|
+
}
|
|
99
|
+
if (attachErrorHandler) {
|
|
100
|
+
const prev = app.config.errorHandler;
|
|
101
|
+
app.config.errorHandler = (err, instance, info) => {
|
|
102
|
+
try {
|
|
103
|
+
js.AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
|
|
104
|
+
framework: "vue",
|
|
105
|
+
componentName: instance?.$options?.name,
|
|
106
|
+
lifecycleHook: info
|
|
107
|
+
});
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
if (prev) prev(err, instance, info);
|
|
111
|
+
else if (undefined?.DEV) {
|
|
112
|
+
console.error(err);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (attachWarnHandler) {
|
|
117
|
+
const prev = app.config.warnHandler;
|
|
118
|
+
app.config.warnHandler = (msg, instance, trace) => {
|
|
119
|
+
try {
|
|
120
|
+
js.AllStak.addBreadcrumb({
|
|
121
|
+
type: "vue.warn",
|
|
122
|
+
message: msg,
|
|
123
|
+
level: "warning",
|
|
124
|
+
data: {
|
|
125
|
+
componentName: instance?.$options?.name,
|
|
126
|
+
trace
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
if (prev) prev(msg, instance, trace);
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
app.provide("$allstak", js.AllStak);
|
|
135
|
+
app.config.globalProperties.$allstak = js.AllStak;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
function useAllStak() {
|
|
139
|
+
return vue.inject("$allstak", js.AllStak);
|
|
140
|
+
}
|
|
141
|
+
function useAllStakUser(user) {
|
|
142
|
+
const allstak = useAllStak();
|
|
143
|
+
if (user) {
|
|
144
|
+
allstak.setUser(user);
|
|
145
|
+
vue.onScopeDispose(() => allstak.setUser({}));
|
|
146
|
+
} else {
|
|
147
|
+
allstak.setUser({});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function useAllStakSpan(opts) {
|
|
151
|
+
const allstak = useAllStak();
|
|
152
|
+
const span = allstak.startSpan(opts.op ?? "custom", opts);
|
|
153
|
+
vue.onScopeDispose(() => {
|
|
154
|
+
try {
|
|
155
|
+
span.finish();
|
|
156
|
+
} catch {
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return span;
|
|
160
|
+
}
|
|
161
|
+
function installRouterInstrumentation(router) {
|
|
162
|
+
let activeNavSpan = null;
|
|
163
|
+
router.beforeEach((to, from) => {
|
|
164
|
+
try {
|
|
165
|
+
js.AllStak.addBreadcrumb({
|
|
166
|
+
type: "navigation",
|
|
167
|
+
message: `${String(from.fullPath)} \u2192 ${String(to.fullPath)}`,
|
|
168
|
+
level: "info",
|
|
169
|
+
data: {
|
|
170
|
+
name: String(to.name ?? ""),
|
|
171
|
+
fullPath: to.fullPath,
|
|
172
|
+
params: to.params,
|
|
173
|
+
query: to.query
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
activeNavSpan = js.AllStak.startSpan("navigation", {
|
|
177
|
+
description: String(to.fullPath),
|
|
178
|
+
attributes: {
|
|
179
|
+
"allstak.origin": "auto.navigation.vue",
|
|
180
|
+
"route.name": String(to.name ?? ""),
|
|
181
|
+
"route.path": to.path
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
} catch {
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
router.afterEach(() => {
|
|
188
|
+
try {
|
|
189
|
+
activeNavSpan?.finish("ok");
|
|
190
|
+
} catch {
|
|
191
|
+
} finally {
|
|
192
|
+
activeNavSpan = null;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
router.onError((err) => {
|
|
196
|
+
try {
|
|
197
|
+
activeNavSpan?.finish("error");
|
|
198
|
+
js.AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
|
|
199
|
+
framework: "vue",
|
|
200
|
+
source: "vue-router"
|
|
201
|
+
});
|
|
202
|
+
} catch {
|
|
203
|
+
} finally {
|
|
204
|
+
activeNavSpan = null;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function useAllStakRouter(router) {
|
|
209
|
+
return installRouterInstrumentation(router);
|
|
210
|
+
}
|
|
211
|
+
var AllStakErrorBoundary = vue.defineComponent({
|
|
212
|
+
name: "AllStakErrorBoundary",
|
|
213
|
+
props: {
|
|
214
|
+
/**
|
|
215
|
+
* Re-throw the error after capturing. Default: `true`. Disable only
|
|
216
|
+
* when this boundary should fully consume the error (i.e. you've
|
|
217
|
+
* supplied a useful `fallback` slot).
|
|
218
|
+
*/
|
|
219
|
+
rethrow: { type: Boolean, default: true }
|
|
220
|
+
},
|
|
221
|
+
setup(props, { slots }) {
|
|
222
|
+
const state = { hasError: false, error: null };
|
|
223
|
+
vue.onErrorCaptured((err, instance, info) => {
|
|
224
|
+
state.hasError = true;
|
|
225
|
+
state.error = err;
|
|
226
|
+
try {
|
|
227
|
+
js.AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
|
|
228
|
+
framework: "vue",
|
|
229
|
+
source: "AllStakErrorBoundary",
|
|
230
|
+
componentName: instance?.$options?.name,
|
|
231
|
+
lifecycleHook: info
|
|
232
|
+
});
|
|
233
|
+
} catch {
|
|
234
|
+
}
|
|
235
|
+
return props.rethrow;
|
|
236
|
+
});
|
|
237
|
+
return () => {
|
|
238
|
+
if (state.hasError && slots.fallback) {
|
|
239
|
+
return slots.fallback({ error: state.error });
|
|
240
|
+
}
|
|
241
|
+
return slots.default ? slots.default() : null;
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
var SDK_NAME = "allstak-vue";
|
|
246
|
+
var SDK_VERSION = "0.1.0";
|
|
247
|
+
|
|
248
|
+
Object.defineProperty(exports, "AllStak", {
|
|
249
|
+
enumerable: true,
|
|
250
|
+
get: function () { return js.AllStak; }
|
|
251
|
+
});
|
|
252
|
+
Object.defineProperty(exports, "Scope", {
|
|
253
|
+
enumerable: true,
|
|
254
|
+
get: function () { return js.Scope; }
|
|
255
|
+
});
|
|
256
|
+
Object.defineProperty(exports, "Session", {
|
|
257
|
+
enumerable: true,
|
|
258
|
+
get: function () { return js.Session; }
|
|
259
|
+
});
|
|
260
|
+
Object.defineProperty(exports, "SessionTracker", {
|
|
261
|
+
enumerable: true,
|
|
262
|
+
get: function () { return js.SessionTracker; }
|
|
263
|
+
});
|
|
264
|
+
Object.defineProperty(exports, "Span", {
|
|
265
|
+
enumerable: true,
|
|
266
|
+
get: function () { return js.Span; }
|
|
267
|
+
});
|
|
268
|
+
Object.defineProperty(exports, "WebVitalsModule", {
|
|
269
|
+
enumerable: true,
|
|
270
|
+
get: function () { return js.WebVitalsModule; }
|
|
271
|
+
});
|
|
272
|
+
Object.defineProperty(exports, "consoleIntegration", {
|
|
273
|
+
enumerable: true,
|
|
274
|
+
get: function () { return js.consoleIntegration; }
|
|
275
|
+
});
|
|
276
|
+
Object.defineProperty(exports, "databaseIntegration", {
|
|
277
|
+
enumerable: true,
|
|
278
|
+
get: function () { return js.databaseIntegration; }
|
|
279
|
+
});
|
|
280
|
+
Object.defineProperty(exports, "dedupeIntegration", {
|
|
281
|
+
enumerable: true,
|
|
282
|
+
get: function () { return js.dedupeIntegration; }
|
|
283
|
+
});
|
|
284
|
+
Object.defineProperty(exports, "defineIntegration", {
|
|
285
|
+
enumerable: true,
|
|
286
|
+
get: function () { return js.defineIntegration; }
|
|
287
|
+
});
|
|
288
|
+
Object.defineProperty(exports, "eventFiltersIntegration", {
|
|
289
|
+
enumerable: true,
|
|
290
|
+
get: function () { return js.eventFiltersIntegration; }
|
|
291
|
+
});
|
|
292
|
+
Object.defineProperty(exports, "httpClientIntegration", {
|
|
293
|
+
enumerable: true,
|
|
294
|
+
get: function () { return js.httpClientIntegration; }
|
|
295
|
+
});
|
|
296
|
+
Object.defineProperty(exports, "inboundFiltersIntegration", {
|
|
297
|
+
enumerable: true,
|
|
298
|
+
get: function () { return js.inboundFiltersIntegration; }
|
|
299
|
+
});
|
|
300
|
+
Object.defineProperty(exports, "isWebVitalsSupported", {
|
|
301
|
+
enumerable: true,
|
|
302
|
+
get: function () { return js.isWebVitalsSupported; }
|
|
303
|
+
});
|
|
304
|
+
exports.AllStakErrorBoundary = AllStakErrorBoundary;
|
|
305
|
+
exports.AllStakPlugin = AllStakPlugin;
|
|
306
|
+
exports.SDK_NAME = SDK_NAME;
|
|
307
|
+
exports.SDK_VERSION = SDK_VERSION;
|
|
308
|
+
exports.createTracingMixins = createTracingMixins;
|
|
309
|
+
exports.init = init;
|
|
310
|
+
exports.installComponentTracing = installComponentTracing;
|
|
311
|
+
exports.installRouterInstrumentation = installRouterInstrumentation;
|
|
312
|
+
exports.useAllStak = useAllStak;
|
|
313
|
+
exports.useAllStakRouter = useAllStakRouter;
|
|
314
|
+
exports.useAllStakSpan = useAllStakSpan;
|
|
315
|
+
exports.useAllStakUser = useAllStakUser;
|
|
316
|
+
//# sourceMappingURL=index.js.map
|
|
317
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/init.ts","../src/tracing-mixin.ts","../src/plugin.ts","../src/composables.ts","../src/router.ts","../src/error-boundary.ts","../src/index.ts"],"names":["AllStak","inject","onScopeDispose","defineComponent","onErrorCaptured"],"mappings":"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","file":"index.js","sourcesContent":["import { AllStak } from '@allstak/js';\nimport type { AllStakConfig } from '@allstak/js';\n\ndeclare const __ALLSTAK_VUE_VERSION__: string;\n\n/**\n * The core client instance returned by `AllStak.init`. `@allstak/js` does\n * not export the `AllStakClient` class by name, so we derive the type from\n * the value. This keeps the emitted declaration referential (no inlining of\n * the core class's private members, which would trip TS4094).\n */\nexport type AllStakClientInstance = ReturnType<typeof AllStak.init>;\n\n/**\n * Initialize the AllStak SDK for a Vue 3 application.\n *\n * This is a thin shim over `AllStak.init` from `@allstak/js` that stamps\n * the wrapper identity (`sdkName`, `sdkVersion`) so the backend can tell\n * Vue traffic apart from plain JS traffic. Everything else — buffering,\n * sampling, session health, offline queue, PII scrubbing — is delegated\n * to the underlying core client.\n *\n * Call this once at app boot, BEFORE `app.use(AllStakPlugin)` if you want\n * the plugin to surface the same client instance.\n */\nexport function init(config: AllStakConfig): AllStakClientInstance {\n return AllStak.init({\n ...config,\n sdkName: config.sdkName ?? 'allstak-vue',\n sdkVersion: config.sdkVersion ?? __ALLSTAK_VUE_VERSION__,\n });\n}\n","import type { App, ComponentOptions } from 'vue';\nimport { AllStak, Span } from '@allstak/js';\n\n/**\n * Component-lifecycle operations that can be traced. Each maps to a\n * before/after lifecycle-hook pair on the Vue component instance.\n */\nexport type TracingOperation = 'mount' | 'update' | 'unmount';\n\nexport interface ComponentTracingOptions {\n /**\n * Which components to trace.\n * - `false` (default): trace nothing.\n * - `true`: trace every component.\n * - `string[]`: trace only components whose name is in the list.\n */\n trackComponents?: boolean | string[];\n\n /**\n * Which lifecycle operations to time. Default: `['mount']`.\n * A span is opened on the `before*` hook and finished on the matching\n * `*ed`/`*ted` hook.\n */\n hooks?: TracingOperation[];\n\n /**\n * Span operation prefix. Resulting spans use `ui.vue.<operation>`\n * (e.g. `ui.vue.mount`). Default: `'ui.vue'`.\n */\n opPrefix?: string;\n}\n\nconst DEFAULT_HOOKS: TracingOperation[] = ['mount'];\nconst OP_PREFIX = 'ui.vue';\n\n/** before → after hook names for each traced operation. */\nconst HOOK_PAIRS: Record<TracingOperation, [string, string]> = {\n mount: ['beforeMount', 'mounted'],\n update: ['beforeUpdate', 'updated'],\n unmount: ['beforeUnmount', 'unmounted'],\n};\n\ninterface TracedInstance {\n $options?: { name?: string; __name?: string; _componentTag?: string };\n $?: { type?: { name?: string; __name?: string } };\n}\n\nfunction componentName(vm: TracedInstance): string {\n const opts = vm.$options ?? {};\n const internal = vm.$?.type ?? {};\n const name =\n opts.name ??\n opts.__name ??\n opts._componentTag ??\n internal.name ??\n internal.__name;\n return name ? String(name) : 'Anonymous Component';\n}\n\nfunction shouldTrack(name: string, trackComponents: boolean | string[]): boolean {\n if (trackComponents === true) return true;\n if (Array.isArray(trackComponents)) return trackComponents.includes(name);\n return false;\n}\n\n/**\n * Build a Vue mixin that opens a span around the configured lifecycle\n * phases of each tracked component. The span is named after the\n * component and tagged with the lifecycle operation, giving render-time\n * visibility comparable to a dedicated component profiler.\n *\n * Spans use operation `ui.vue.<operation>` and description\n * `Vue <ComponentName>`.\n */\nexport function createTracingMixins(\n options: ComponentTracingOptions = {},\n): ComponentOptions {\n const trackComponents = options.trackComponents ?? false;\n const hooks = options.hooks ?? DEFAULT_HOOKS;\n const opPrefix = options.opPrefix ?? OP_PREFIX;\n\n const mixin: ComponentOptions = {};\n\n // Per-instance span registry, keyed by operation. We key on the\n // instance via a WeakMap-free closure-per-hook approach: each hook\n // stores its span on a private field on the instance.\n const SPAN_KEY = '__allstak_spans__';\n\n type SpanBag = Partial<Record<TracingOperation, Span>>;\n\n for (const op of hooks) {\n const pair = HOOK_PAIRS[op];\n if (!pair) continue;\n const [before, after] = pair;\n\n (mixin as Record<string, unknown>)[before] = function (this: TracedInstance) {\n const name = componentName(this);\n if (!shouldTrack(name, trackComponents)) return;\n try {\n const span = AllStak.startSpan(`${opPrefix}.${op}`, {\n op: `${opPrefix}.${op}`,\n description: `Vue ${name}`,\n attributes: {\n 'allstak.origin': 'auto.ui.vue',\n 'vue.component': name,\n 'vue.operation': op,\n },\n });\n const self = this as unknown as Record<string, SpanBag | undefined>;\n const bag = (self[SPAN_KEY] ??= {});\n bag[op] = span;\n } catch {\n // Never let render-tracing break a component.\n }\n };\n\n (mixin as Record<string, unknown>)[after] = function (this: TracedInstance) {\n try {\n const self = this as unknown as Record<string, SpanBag | undefined>;\n const bag = self[SPAN_KEY];\n const span = bag?.[op];\n if (span) {\n span.finish('ok');\n delete bag[op];\n }\n } catch {\n // ignore\n }\n };\n }\n\n return mixin;\n}\n\n/**\n * Install component performance tracing on a Vue app via `app.mixin`.\n *\n * import { createApp } from 'vue';\n * import { installComponentTracing } from '@allstak/vue';\n *\n * const app = createApp(App);\n * installComponentTracing(app, { trackComponents: true });\n */\nexport function installComponentTracing(\n app: App,\n options: ComponentTracingOptions = {},\n): void {\n // No-op when nothing is tracked, to avoid installing an empty mixin.\n const trackComponents = options.trackComponents ?? false;\n if (trackComponents === false) return;\n if (Array.isArray(trackComponents) && trackComponents.length === 0) return;\n app.mixin(createTracingMixins(options));\n}\n","import type { App, Plugin } from 'vue';\nimport { AllStak } from '@allstak/js';\nimport type { AllStakConfig } from '@allstak/js';\nimport { init } from './init';\nimport { installComponentTracing } from './tracing-mixin';\nimport type { ComponentTracingOptions } from './tracing-mixin';\n\nexport interface AllStakVueOptions extends AllStakConfig {\n /**\n * Hook into `app.config.errorHandler` to capture every uncaught error\n * thrown from a render function or watcher. Default: `true`.\n *\n * Set to `false` if you have your own error handler and want to call\n * `AllStak.captureException` from it manually.\n */\n attachErrorHandler?: boolean;\n\n /**\n * Hook into `app.config.warnHandler` to capture every Vue warning as a\n * breadcrumb. Useful while you're stabilising — turn it off in prod\n * for noisy apps. Default: `false`.\n */\n attachWarnHandler?: boolean;\n\n /**\n * Skip calling `AllStak.init`. Pass this when you've already called\n * `init(...)` yourself (or imported a module that did) and just want\n * the plugin's Vue-side hooks. Default: `false`.\n */\n skipInit?: boolean;\n\n /**\n * Component-render performance tracing. When `trackComponents` is set\n * (to `true` or a list of component names), a span is opened around\n * each tracked component's lifecycle phase. Disabled by default.\n */\n tracingOptions?: ComponentTracingOptions;\n}\n\n/**\n * Vue 3 plugin.\n *\n * import { createApp } from 'vue';\n * import { AllStakPlugin } from '@allstak/vue';\n * import App from './App.vue';\n *\n * createApp(App)\n * .use(AllStakPlugin, {\n * apiKey: import.meta.env.VITE_ALLSTAK_API_KEY,\n * environment: import.meta.env.MODE,\n * release: import.meta.env.VITE_APP_VERSION,\n * })\n * .mount('#app');\n */\nexport const AllStakPlugin: Plugin = {\n install(app: App, options: AllStakVueOptions = {} as AllStakVueOptions) {\n const {\n attachErrorHandler = true,\n attachWarnHandler = false,\n skipInit = false,\n tracingOptions,\n ...config\n } = options;\n\n if (!skipInit) {\n init(config);\n }\n\n if (tracingOptions) {\n installComponentTracing(app, tracingOptions);\n }\n\n if (attachErrorHandler) {\n const prev = app.config.errorHandler;\n app.config.errorHandler = (err, instance, info) => {\n try {\n AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {\n framework: 'vue',\n componentName: (instance as { $options?: { name?: string } } | null)?.$options?.name,\n lifecycleHook: info,\n });\n } catch {\n // Never let our handler break the host's error path.\n }\n if (prev) prev(err, instance, info);\n else if (import.meta?.env?.DEV) {\n // Keep Vue's default dev console output when no prior handler.\n // eslint-disable-next-line no-console\n console.error(err);\n }\n };\n }\n\n if (attachWarnHandler) {\n const prev = app.config.warnHandler;\n app.config.warnHandler = (msg, instance, trace) => {\n try {\n AllStak.addBreadcrumb({\n type: 'vue.warn',\n message: msg,\n level: 'warning',\n data: {\n componentName: (instance as { $options?: { name?: string } } | null)?.$options?.name,\n trace,\n },\n });\n } catch {\n // ignore\n }\n if (prev) prev(msg, instance, trace);\n };\n }\n\n // Expose under both names so users can use either pattern:\n // inject('$allstak') → composition API\n // this.$allstak → options API\n app.provide('$allstak', AllStak);\n app.config.globalProperties.$allstak = AllStak;\n },\n};\n","import { inject, onScopeDispose } from 'vue';\nimport { AllStak, Span } from '@allstak/js';\nimport type { SpanOptions } from '@allstak/js';\n\ntype AllStakNS = typeof AllStak;\n\n/**\n * Access the AllStak client inside a `<script setup>` block.\n *\n * import { useAllStak } from '@allstak/vue';\n *\n * const allstak = useAllStak();\n * allstak.captureException(new Error('boom'));\n */\nexport function useAllStak(): AllStakNS {\n // We try injection first (set up by AllStakPlugin) and fall back to the\n // singleton import. The fallback path lets users call composables in\n // tests or in setup() before the plugin has been installed.\n return inject<AllStakNS>('$allstak', AllStak);\n}\n\n/**\n * Set the active user for the duration of this component's lifetime,\n * automatically clearing it on unmount.\n *\n * useAllStakUser({ id: currentUser.value.id, email: currentUser.value.email });\n *\n * The core client identifies users by `id` and/or `email` only. To clear\n * the user we call `setUser({})` (there is no dedicated clear method).\n */\nexport function useAllStakUser(user: {\n id?: string;\n email?: string;\n} | null) {\n const allstak = useAllStak();\n if (user) {\n allstak.setUser(user);\n onScopeDispose(() => allstak.setUser({}));\n } else {\n allstak.setUser({});\n }\n}\n\n/**\n * Open a span and finish it when the component (or effect scope) tears\n * down. Mirrors the pattern of React's `useSpan`.\n *\n * const span = useAllStakSpan({ op: 'checkout.flow', description: 'review → pay' });\n * span.setTag('flow', 'web');\n */\nexport function useAllStakSpan(opts: SpanOptions): Span {\n const allstak = useAllStak();\n const span = allstak.startSpan(opts.op ?? 'custom', opts);\n onScopeDispose(() => {\n try {\n span.finish();\n } catch {\n // ignore — span may already be finished\n }\n });\n return span;\n}\n","import { AllStak } from '@allstak/js';\nimport type { Span } from '@allstak/js';\nimport type { Router } from 'vue-router';\n\n/**\n * Instrument vue-router so every route change opens a navigation span +\n * a breadcrumb.\n *\n * import { createRouter } from 'vue-router';\n * import { installRouterInstrumentation } from '@allstak/vue';\n *\n * const router = createRouter({ ... });\n * installRouterInstrumentation(router);\n *\n * Or composition-API style:\n *\n * const router = useRouter();\n * useAllStakRouter(router);\n */\nexport function installRouterInstrumentation(router: Router) {\n let activeNavSpan: Span | null = null;\n\n router.beforeEach((to, from) => {\n try {\n AllStak.addBreadcrumb({\n type: 'navigation',\n message: `${String(from.fullPath)} → ${String(to.fullPath)}`,\n level: 'info',\n data: {\n name: String(to.name ?? ''),\n fullPath: to.fullPath,\n params: to.params,\n query: to.query,\n },\n });\n\n activeNavSpan = AllStak.startSpan('navigation', {\n description: String(to.fullPath),\n attributes: {\n 'allstak.origin': 'auto.navigation.vue',\n 'route.name': String(to.name ?? ''),\n 'route.path': to.path,\n },\n });\n } catch {\n // ignore — never block navigation on observability errors\n }\n });\n\n router.afterEach(() => {\n try {\n activeNavSpan?.finish('ok');\n } catch {\n // ignore\n } finally {\n activeNavSpan = null;\n }\n });\n\n router.onError((err) => {\n try {\n activeNavSpan?.finish('error');\n AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {\n framework: 'vue',\n source: 'vue-router',\n });\n } catch {\n // ignore\n } finally {\n activeNavSpan = null;\n }\n });\n}\n\n/** Composable-style alias for `installRouterInstrumentation`. */\nexport function useAllStakRouter(router: Router) {\n return installRouterInstrumentation(router);\n}\n","import { defineComponent, onErrorCaptured, h } from 'vue';\nimport { AllStak } from '@allstak/js';\n\n/**\n * A drop-in error boundary component that reports any error thrown in\n * its subtree to AllStak and then re-throws so the next boundary up the\n * tree (or the global handler) still sees it.\n *\n * <AllStakErrorBoundary>\n * <RiskyWidget />\n * </AllStakErrorBoundary>\n *\n * Slots:\n * default — the wrapped subtree\n * fallback — optional; if provided, rendered when the subtree throws.\n * Receives `{ error }` as a slot prop.\n */\nexport const AllStakErrorBoundary = defineComponent({\n name: 'AllStakErrorBoundary',\n props: {\n /**\n * Re-throw the error after capturing. Default: `true`. Disable only\n * when this boundary should fully consume the error (i.e. you've\n * supplied a useful `fallback` slot).\n */\n rethrow: { type: Boolean, default: true },\n },\n setup(props, { slots }) {\n const state = { hasError: false, error: null as unknown };\n\n onErrorCaptured((err, instance, info) => {\n state.hasError = true;\n state.error = err;\n try {\n AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {\n framework: 'vue',\n source: 'AllStakErrorBoundary',\n componentName: (instance as { $options?: { name?: string } } | null)?.$options?.name,\n lifecycleHook: info,\n });\n } catch {\n // ignore\n }\n // Returning `false` swallows the error here; returning anything\n // else (or nothing) lets it propagate. Honour `rethrow` prop.\n return props.rethrow;\n });\n\n return () => {\n if (state.hasError && slots.fallback) {\n return slots.fallback({ error: state.error });\n }\n return slots.default ? slots.default() : null;\n };\n },\n});\n","/**\n * AllStak for Vue 3.\n *\n * Public surface:\n * - `init` — bootstrap (delegates to @allstak/js with Vue tagging)\n * - `AllStakPlugin` — `app.use(AllStakPlugin, { apiKey, ... })`\n * - `useAllStak` — composition API access to the client\n * - `useAllStakUser` — set/clear user from inside a setup()\n * - `useAllStakSpan` — open a manual span within a setup\n * - `useAllStakRouter` — instrument vue-router (route change → span)\n * - `AllStakErrorBoundary` — re-throwing error boundary component\n * - `createTracingMixins` / `installComponentTracing` — component-render spans\n * - re-exports — every top-level @allstak/js export\n */\n\nexport { init } from './init';\nexport { AllStakPlugin } from './plugin';\nexport type { AllStakVueOptions } from './plugin';\nexport {\n useAllStak,\n useAllStakUser,\n useAllStakSpan,\n} from './composables';\nexport { useAllStakRouter, installRouterInstrumentation } from './router';\nexport { AllStakErrorBoundary } from './error-boundary';\nexport {\n createTracingMixins,\n installComponentTracing,\n} from './tracing-mixin';\nexport type {\n ComponentTracingOptions,\n TracingOperation,\n} from './tracing-mixin';\n\n// Mirror the @allstak/js public surface so consumers can pull the entire\n// observability API from a single namespaced import.\nexport {\n AllStak,\n Scope,\n Session,\n SessionTracker,\n Span,\n WebVitalsModule,\n isWebVitalsSupported,\n defineIntegration,\n dedupeIntegration,\n consoleIntegration,\n httpClientIntegration,\n databaseIntegration,\n eventFiltersIntegration,\n inboundFiltersIntegration,\n} from '@allstak/js';\n\nexport type {\n AllStakConfig,\n AllStakIntegration,\n Breadcrumb,\n ErrorEvent,\n ErrorEventProcessor,\n LogEvent,\n LogLevel,\n HttpRequestItem,\n HeartbeatOptions,\n SpanData,\n SpanOptions,\n SpanProcessor,\n TracesSampler,\n SamplingContext,\n WebVitalsContext,\n DbQueryItem,\n SessionStatus,\n} from '@allstak/js';\n\nexport const SDK_NAME = 'allstak-vue';\ndeclare const __ALLSTAK_VUE_VERSION__: string;\nexport const SDK_VERSION = __ALLSTAK_VUE_VERSION__;\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { AllStak } from '@allstak/js';
|
|
2
|
+
export { AllStak, Scope, Session, SessionTracker, Span, WebVitalsModule, consoleIntegration, databaseIntegration, dedupeIntegration, defineIntegration, eventFiltersIntegration, httpClientIntegration, inboundFiltersIntegration, isWebVitalsSupported } from '@allstak/js';
|
|
3
|
+
import { defineComponent, onErrorCaptured, inject, onScopeDispose } from 'vue';
|
|
4
|
+
|
|
5
|
+
// src/init.ts
|
|
6
|
+
function init(config) {
|
|
7
|
+
return AllStak.init({
|
|
8
|
+
...config,
|
|
9
|
+
sdkName: config.sdkName ?? "allstak-vue",
|
|
10
|
+
sdkVersion: config.sdkVersion ?? "0.1.0"
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
var DEFAULT_HOOKS = ["mount"];
|
|
14
|
+
var OP_PREFIX = "ui.vue";
|
|
15
|
+
var HOOK_PAIRS = {
|
|
16
|
+
mount: ["beforeMount", "mounted"],
|
|
17
|
+
update: ["beforeUpdate", "updated"],
|
|
18
|
+
unmount: ["beforeUnmount", "unmounted"]
|
|
19
|
+
};
|
|
20
|
+
function componentName(vm) {
|
|
21
|
+
const opts = vm.$options ?? {};
|
|
22
|
+
const internal = vm.$?.type ?? {};
|
|
23
|
+
const name = opts.name ?? opts.__name ?? opts._componentTag ?? internal.name ?? internal.__name;
|
|
24
|
+
return name ? String(name) : "Anonymous Component";
|
|
25
|
+
}
|
|
26
|
+
function shouldTrack(name, trackComponents) {
|
|
27
|
+
if (trackComponents === true) return true;
|
|
28
|
+
if (Array.isArray(trackComponents)) return trackComponents.includes(name);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
function createTracingMixins(options = {}) {
|
|
32
|
+
const trackComponents = options.trackComponents ?? false;
|
|
33
|
+
const hooks = options.hooks ?? DEFAULT_HOOKS;
|
|
34
|
+
const opPrefix = options.opPrefix ?? OP_PREFIX;
|
|
35
|
+
const mixin = {};
|
|
36
|
+
const SPAN_KEY = "__allstak_spans__";
|
|
37
|
+
for (const op of hooks) {
|
|
38
|
+
const pair = HOOK_PAIRS[op];
|
|
39
|
+
if (!pair) continue;
|
|
40
|
+
const [before, after] = pair;
|
|
41
|
+
mixin[before] = function() {
|
|
42
|
+
const name = componentName(this);
|
|
43
|
+
if (!shouldTrack(name, trackComponents)) return;
|
|
44
|
+
try {
|
|
45
|
+
const span = AllStak.startSpan(`${opPrefix}.${op}`, {
|
|
46
|
+
op: `${opPrefix}.${op}`,
|
|
47
|
+
description: `Vue ${name}`,
|
|
48
|
+
attributes: {
|
|
49
|
+
"allstak.origin": "auto.ui.vue",
|
|
50
|
+
"vue.component": name,
|
|
51
|
+
"vue.operation": op
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const self = this;
|
|
55
|
+
const bag = self[SPAN_KEY] ?? (self[SPAN_KEY] = {});
|
|
56
|
+
bag[op] = span;
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
mixin[after] = function() {
|
|
61
|
+
try {
|
|
62
|
+
const self = this;
|
|
63
|
+
const bag = self[SPAN_KEY];
|
|
64
|
+
const span = bag?.[op];
|
|
65
|
+
if (span) {
|
|
66
|
+
span.finish("ok");
|
|
67
|
+
delete bag[op];
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return mixin;
|
|
74
|
+
}
|
|
75
|
+
function installComponentTracing(app, options = {}) {
|
|
76
|
+
const trackComponents = options.trackComponents ?? false;
|
|
77
|
+
if (trackComponents === false) return;
|
|
78
|
+
if (Array.isArray(trackComponents) && trackComponents.length === 0) return;
|
|
79
|
+
app.mixin(createTracingMixins(options));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/plugin.ts
|
|
83
|
+
var AllStakPlugin = {
|
|
84
|
+
install(app, options = {}) {
|
|
85
|
+
const {
|
|
86
|
+
attachErrorHandler = true,
|
|
87
|
+
attachWarnHandler = false,
|
|
88
|
+
skipInit = false,
|
|
89
|
+
tracingOptions,
|
|
90
|
+
...config
|
|
91
|
+
} = options;
|
|
92
|
+
if (!skipInit) {
|
|
93
|
+
init(config);
|
|
94
|
+
}
|
|
95
|
+
if (tracingOptions) {
|
|
96
|
+
installComponentTracing(app, tracingOptions);
|
|
97
|
+
}
|
|
98
|
+
if (attachErrorHandler) {
|
|
99
|
+
const prev = app.config.errorHandler;
|
|
100
|
+
app.config.errorHandler = (err, instance, info) => {
|
|
101
|
+
try {
|
|
102
|
+
AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
|
|
103
|
+
framework: "vue",
|
|
104
|
+
componentName: instance?.$options?.name,
|
|
105
|
+
lifecycleHook: info
|
|
106
|
+
});
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
if (prev) prev(err, instance, info);
|
|
110
|
+
else if (import.meta?.env?.DEV) {
|
|
111
|
+
console.error(err);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (attachWarnHandler) {
|
|
116
|
+
const prev = app.config.warnHandler;
|
|
117
|
+
app.config.warnHandler = (msg, instance, trace) => {
|
|
118
|
+
try {
|
|
119
|
+
AllStak.addBreadcrumb({
|
|
120
|
+
type: "vue.warn",
|
|
121
|
+
message: msg,
|
|
122
|
+
level: "warning",
|
|
123
|
+
data: {
|
|
124
|
+
componentName: instance?.$options?.name,
|
|
125
|
+
trace
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
if (prev) prev(msg, instance, trace);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
app.provide("$allstak", AllStak);
|
|
134
|
+
app.config.globalProperties.$allstak = AllStak;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
function useAllStak() {
|
|
138
|
+
return inject("$allstak", AllStak);
|
|
139
|
+
}
|
|
140
|
+
function useAllStakUser(user) {
|
|
141
|
+
const allstak = useAllStak();
|
|
142
|
+
if (user) {
|
|
143
|
+
allstak.setUser(user);
|
|
144
|
+
onScopeDispose(() => allstak.setUser({}));
|
|
145
|
+
} else {
|
|
146
|
+
allstak.setUser({});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function useAllStakSpan(opts) {
|
|
150
|
+
const allstak = useAllStak();
|
|
151
|
+
const span = allstak.startSpan(opts.op ?? "custom", opts);
|
|
152
|
+
onScopeDispose(() => {
|
|
153
|
+
try {
|
|
154
|
+
span.finish();
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
return span;
|
|
159
|
+
}
|
|
160
|
+
function installRouterInstrumentation(router) {
|
|
161
|
+
let activeNavSpan = null;
|
|
162
|
+
router.beforeEach((to, from) => {
|
|
163
|
+
try {
|
|
164
|
+
AllStak.addBreadcrumb({
|
|
165
|
+
type: "navigation",
|
|
166
|
+
message: `${String(from.fullPath)} \u2192 ${String(to.fullPath)}`,
|
|
167
|
+
level: "info",
|
|
168
|
+
data: {
|
|
169
|
+
name: String(to.name ?? ""),
|
|
170
|
+
fullPath: to.fullPath,
|
|
171
|
+
params: to.params,
|
|
172
|
+
query: to.query
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
activeNavSpan = AllStak.startSpan("navigation", {
|
|
176
|
+
description: String(to.fullPath),
|
|
177
|
+
attributes: {
|
|
178
|
+
"allstak.origin": "auto.navigation.vue",
|
|
179
|
+
"route.name": String(to.name ?? ""),
|
|
180
|
+
"route.path": to.path
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
router.afterEach(() => {
|
|
187
|
+
try {
|
|
188
|
+
activeNavSpan?.finish("ok");
|
|
189
|
+
} catch {
|
|
190
|
+
} finally {
|
|
191
|
+
activeNavSpan = null;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
router.onError((err) => {
|
|
195
|
+
try {
|
|
196
|
+
activeNavSpan?.finish("error");
|
|
197
|
+
AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
|
|
198
|
+
framework: "vue",
|
|
199
|
+
source: "vue-router"
|
|
200
|
+
});
|
|
201
|
+
} catch {
|
|
202
|
+
} finally {
|
|
203
|
+
activeNavSpan = null;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function useAllStakRouter(router) {
|
|
208
|
+
return installRouterInstrumentation(router);
|
|
209
|
+
}
|
|
210
|
+
var AllStakErrorBoundary = defineComponent({
|
|
211
|
+
name: "AllStakErrorBoundary",
|
|
212
|
+
props: {
|
|
213
|
+
/**
|
|
214
|
+
* Re-throw the error after capturing. Default: `true`. Disable only
|
|
215
|
+
* when this boundary should fully consume the error (i.e. you've
|
|
216
|
+
* supplied a useful `fallback` slot).
|
|
217
|
+
*/
|
|
218
|
+
rethrow: { type: Boolean, default: true }
|
|
219
|
+
},
|
|
220
|
+
setup(props, { slots }) {
|
|
221
|
+
const state = { hasError: false, error: null };
|
|
222
|
+
onErrorCaptured((err, instance, info) => {
|
|
223
|
+
state.hasError = true;
|
|
224
|
+
state.error = err;
|
|
225
|
+
try {
|
|
226
|
+
AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
|
|
227
|
+
framework: "vue",
|
|
228
|
+
source: "AllStakErrorBoundary",
|
|
229
|
+
componentName: instance?.$options?.name,
|
|
230
|
+
lifecycleHook: info
|
|
231
|
+
});
|
|
232
|
+
} catch {
|
|
233
|
+
}
|
|
234
|
+
return props.rethrow;
|
|
235
|
+
});
|
|
236
|
+
return () => {
|
|
237
|
+
if (state.hasError && slots.fallback) {
|
|
238
|
+
return slots.fallback({ error: state.error });
|
|
239
|
+
}
|
|
240
|
+
return slots.default ? slots.default() : null;
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
var SDK_NAME = "allstak-vue";
|
|
245
|
+
var SDK_VERSION = "0.1.0";
|
|
246
|
+
|
|
247
|
+
export { AllStakErrorBoundary, AllStakPlugin, SDK_NAME, SDK_VERSION, createTracingMixins, init, installComponentTracing, installRouterInstrumentation, useAllStak, useAllStakRouter, useAllStakSpan, useAllStakUser };
|
|
248
|
+
//# sourceMappingURL=index.mjs.map
|
|
249
|
+
//# sourceMappingURL=index.mjs.map
|