@allstak/vue 0.1.0 → 0.2.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 CHANGED
@@ -5,6 +5,25 @@ All notable changes to `@allstak/vue` are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] — 2026-05-30
9
+
10
+ ### Added
11
+
12
+ - **Automatic vue-router instrumentation.** `AllStakPlugin` now installs router
13
+ navigation instrumentation on its own — no manual `installRouterInstrumentation`
14
+ call required. The plugin resolves the router from the new `router` option or,
15
+ failing that, from `app.config.globalProperties.$router` (set by
16
+ `app.use(router)`), then wires navigation spans and breadcrumbs automatically.
17
+ - On by default via the new `autoInstrumentRouter` option (`true`); set it to
18
+ `false` to opt out and wire instrumentation by hand.
19
+ - Safe no-op when vue-router isn't installed or no router can be resolved.
20
+ - `installRouterInstrumentation` is now idempotent, so automatic and manual
21
+ instrumentation of the same router never double-register navigation guards.
22
+ - The manual `installRouterInstrumentation` / `useAllStakRouter` exports are
23
+ unchanged and still available.
24
+
25
+ [0.2.0]: https://github.com/AllStak/allstak-vue/releases/tag/v0.2.0
26
+
8
27
  ## [0.1.0] — 2026-05-29
9
28
 
10
29
  Initial release of the official AllStak SDK for Vue 3.
package/README.md CHANGED
@@ -58,15 +58,45 @@ span.setTag('cart_size', items.value.length);
58
58
 
59
59
  ## vue-router
60
60
 
61
+ Navigation instrumentation is **automatic**. Register vue-router before the
62
+ plugin (or pass the router via the `router` option) and every route change
63
+ becomes a `navigation` span + breadcrumb — no extra call required:
64
+
61
65
  ```ts
66
+ import { createApp } from 'vue';
62
67
  import { createRouter, createWebHistory } from 'vue-router';
68
+ import { AllStakPlugin } from '@allstak/vue';
69
+ import App from './App.vue';
70
+
71
+ const router = createRouter({ history: createWebHistory(), routes });
72
+
73
+ createApp(App)
74
+ .use(router) // register the router first, then…
75
+ .use(AllStakPlugin, { apiKey: import.meta.env.VITE_ALLSTAK_API_KEY })
76
+ .mount('#app');
77
+ ```
78
+
79
+ If the plugin runs before `app.use(router)`, pass the router explicitly:
80
+
81
+ ```ts
82
+ createApp(App)
83
+ .use(AllStakPlugin, { apiKey: '…', router })
84
+ .use(router)
85
+ .mount('#app');
86
+ ```
87
+
88
+ You can still wire it by hand (e.g. when `autoInstrumentRouter: false`):
89
+
90
+ ```ts
63
91
  import { installRouterInstrumentation } from '@allstak/vue';
64
92
 
65
93
  const router = createRouter({ history: createWebHistory(), routes });
66
94
  installRouterInstrumentation(router);
67
95
  ```
68
96
 
69
- Every navigation becomes a `navigation` span + breadcrumb. Router errors become Issues.
97
+ Auto-instrumentation is on by default and a safe no-op when vue-router isn't
98
+ installed; set `autoInstrumentRouter: false` to opt out. Router errors become
99
+ Issues. Instrumenting the same router twice is a no-op.
70
100
 
71
101
  ## Component performance tracing
72
102
 
package/dist/index.d.mts CHANGED
@@ -98,21 +98,47 @@ interface AllStakVueOptions extends AllStakConfig {
98
98
  * each tracked component's lifecycle phase. Disabled by default.
99
99
  */
100
100
  tracingOptions?: ComponentTracingOptions;
101
+ /**
102
+ * Automatically instrument vue-router so every route change opens a
103
+ * navigation span + breadcrumb — no manual `installRouterInstrumentation`
104
+ * call required. Default: `true`.
105
+ *
106
+ * The plugin resolves the router from (in order):
107
+ * 1. the explicit `router` option below, then
108
+ * 2. `app.config.globalProperties.$router` (set by `app.use(router)`).
109
+ *
110
+ * When vue-router is not installed, no router is found, or you've already
111
+ * instrumented the router yourself, this is a safe no-op. Set to `false`
112
+ * to opt out entirely and wire the router instrumentation by hand.
113
+ */
114
+ autoInstrumentRouter?: boolean;
115
+ /**
116
+ * The vue-router instance to auto-instrument. Optional — when omitted the
117
+ * plugin falls back to `app.config.globalProperties.$router`. Provide this
118
+ * (or register the router with `app.use(router)` before
119
+ * `app.use(AllStakPlugin)`) so navigation spans are captured automatically.
120
+ */
121
+ router?: Router;
101
122
  }
102
123
  /**
103
124
  * Vue 3 plugin.
104
125
  *
105
126
  * import { createApp } from 'vue';
106
127
  * import { AllStakPlugin } from '@allstak/vue';
128
+ * import { router } from './router';
107
129
  * import App from './App.vue';
108
130
  *
109
131
  * createApp(App)
110
- * .use(AllStakPlugin, {
132
+ * .use(router) // register vue-router first, and …
133
+ * .use(AllStakPlugin, { // … navigation spans are wired automatically.
111
134
  * apiKey: import.meta.env.VITE_ALLSTAK_API_KEY,
112
135
  * environment: import.meta.env.MODE,
113
136
  * release: import.meta.env.VITE_APP_VERSION,
114
137
  * })
115
138
  * .mount('#app');
139
+ *
140
+ * If you install the plugin before the router (or want to be explicit),
141
+ * pass it directly: `.use(AllStakPlugin, { apiKey, router })`.
116
142
  */
117
143
  declare const AllStakPlugin: Plugin;
118
144
 
@@ -152,6 +178,12 @@ declare function useAllStakSpan(opts: SpanOptions): Span;
152
178
  * Instrument vue-router so every route change opens a navigation span +
153
179
  * a breadcrumb.
154
180
  *
181
+ * As of v0.2.0 the {@link AllStakPlugin} calls this automatically when it
182
+ * can resolve a router (default-on, see `autoInstrumentRouter`), so most
183
+ * apps no longer need to call it by hand. It remains exported for apps that
184
+ * opt out of auto-instrumentation or want to wire a router the plugin can't
185
+ * reach. Calling it more than once on the same router is a safe no-op.
186
+ *
155
187
  * import { createRouter } from 'vue-router';
156
188
  * import { installRouterInstrumentation } from '@allstak/vue';
157
189
  *
package/dist/index.d.ts CHANGED
@@ -98,21 +98,47 @@ interface AllStakVueOptions extends AllStakConfig {
98
98
  * each tracked component's lifecycle phase. Disabled by default.
99
99
  */
100
100
  tracingOptions?: ComponentTracingOptions;
101
+ /**
102
+ * Automatically instrument vue-router so every route change opens a
103
+ * navigation span + breadcrumb — no manual `installRouterInstrumentation`
104
+ * call required. Default: `true`.
105
+ *
106
+ * The plugin resolves the router from (in order):
107
+ * 1. the explicit `router` option below, then
108
+ * 2. `app.config.globalProperties.$router` (set by `app.use(router)`).
109
+ *
110
+ * When vue-router is not installed, no router is found, or you've already
111
+ * instrumented the router yourself, this is a safe no-op. Set to `false`
112
+ * to opt out entirely and wire the router instrumentation by hand.
113
+ */
114
+ autoInstrumentRouter?: boolean;
115
+ /**
116
+ * The vue-router instance to auto-instrument. Optional — when omitted the
117
+ * plugin falls back to `app.config.globalProperties.$router`. Provide this
118
+ * (or register the router with `app.use(router)` before
119
+ * `app.use(AllStakPlugin)`) so navigation spans are captured automatically.
120
+ */
121
+ router?: Router;
101
122
  }
102
123
  /**
103
124
  * Vue 3 plugin.
104
125
  *
105
126
  * import { createApp } from 'vue';
106
127
  * import { AllStakPlugin } from '@allstak/vue';
128
+ * import { router } from './router';
107
129
  * import App from './App.vue';
108
130
  *
109
131
  * createApp(App)
110
- * .use(AllStakPlugin, {
132
+ * .use(router) // register vue-router first, and …
133
+ * .use(AllStakPlugin, { // … navigation spans are wired automatically.
111
134
  * apiKey: import.meta.env.VITE_ALLSTAK_API_KEY,
112
135
  * environment: import.meta.env.MODE,
113
136
  * release: import.meta.env.VITE_APP_VERSION,
114
137
  * })
115
138
  * .mount('#app');
139
+ *
140
+ * If you install the plugin before the router (or want to be explicit),
141
+ * pass it directly: `.use(AllStakPlugin, { apiKey, router })`.
116
142
  */
117
143
  declare const AllStakPlugin: Plugin;
118
144
 
@@ -152,6 +178,12 @@ declare function useAllStakSpan(opts: SpanOptions): Span;
152
178
  * Instrument vue-router so every route change opens a navigation span +
153
179
  * a breadcrumb.
154
180
  *
181
+ * As of v0.2.0 the {@link AllStakPlugin} calls this automatically when it
182
+ * can resolve a router (default-on, see `autoInstrumentRouter`), so most
183
+ * apps no longer need to call it by hand. It remains exported for apps that
184
+ * opt out of auto-instrumentation or want to wire a router the plugin can't
185
+ * reach. Calling it more than once on the same router is a safe no-op.
186
+ *
155
187
  * import { createRouter } from 'vue-router';
156
188
  * import { installRouterInstrumentation } from '@allstak/vue';
157
189
  *
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ function init(config) {
8
8
  return js.AllStak.init({
9
9
  ...config,
10
10
  sdkName: config.sdkName ?? "allstak-vue",
11
- sdkVersion: config.sdkVersion ?? "0.1.0"
11
+ sdkVersion: config.sdkVersion ?? "0.2.0"
12
12
  });
13
13
  }
14
14
  var DEFAULT_HOOKS = ["mount"];
@@ -79,15 +79,81 @@ function installComponentTracing(app, options = {}) {
79
79
  if (Array.isArray(trackComponents) && trackComponents.length === 0) return;
80
80
  app.mixin(createTracingMixins(options));
81
81
  }
82
+ var ROUTER_INSTRUMENTED = "__allstak_router_instrumented__";
83
+ function installRouterInstrumentation(router) {
84
+ const marked = router;
85
+ if (marked[ROUTER_INSTRUMENTED]) return;
86
+ marked[ROUTER_INSTRUMENTED] = true;
87
+ let activeNavSpan = null;
88
+ router.beforeEach((to, from) => {
89
+ try {
90
+ js.AllStak.addBreadcrumb({
91
+ type: "navigation",
92
+ message: `${String(from.fullPath)} \u2192 ${String(to.fullPath)}`,
93
+ level: "info",
94
+ data: {
95
+ name: String(to.name ?? ""),
96
+ fullPath: to.fullPath,
97
+ params: to.params,
98
+ query: to.query
99
+ }
100
+ });
101
+ activeNavSpan = js.AllStak.startSpan("navigation", {
102
+ description: String(to.fullPath),
103
+ attributes: {
104
+ "allstak.origin": "auto.navigation.vue",
105
+ "route.name": String(to.name ?? ""),
106
+ "route.path": to.path
107
+ }
108
+ });
109
+ } catch {
110
+ }
111
+ });
112
+ router.afterEach(() => {
113
+ try {
114
+ activeNavSpan?.finish("ok");
115
+ } catch {
116
+ } finally {
117
+ activeNavSpan = null;
118
+ }
119
+ });
120
+ router.onError((err) => {
121
+ try {
122
+ activeNavSpan?.finish("error");
123
+ js.AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
124
+ framework: "vue",
125
+ source: "vue-router"
126
+ });
127
+ } catch {
128
+ } finally {
129
+ activeNavSpan = null;
130
+ }
131
+ });
132
+ }
133
+ function useAllStakRouter(router) {
134
+ return installRouterInstrumentation(router);
135
+ }
82
136
 
83
137
  // src/plugin.ts
138
+ function autoInstallRouter(app, explicit) {
139
+ try {
140
+ const candidate = explicit ?? app.config.globalProperties.$router;
141
+ if (!candidate || typeof candidate.beforeEach !== "function") {
142
+ return;
143
+ }
144
+ installRouterInstrumentation(candidate);
145
+ } catch {
146
+ }
147
+ }
84
148
  var AllStakPlugin = {
85
149
  install(app, options = {}) {
86
150
  const {
87
151
  attachErrorHandler = true,
88
152
  attachWarnHandler = false,
89
153
  skipInit = false,
154
+ autoInstrumentRouter = true,
90
155
  tracingOptions,
156
+ router,
91
157
  ...config
92
158
  } = options;
93
159
  if (!skipInit) {
@@ -96,6 +162,9 @@ var AllStakPlugin = {
96
162
  if (tracingOptions) {
97
163
  installComponentTracing(app, tracingOptions);
98
164
  }
165
+ if (autoInstrumentRouter) {
166
+ autoInstallRouter(app, router);
167
+ }
99
168
  if (attachErrorHandler) {
100
169
  const prev = app.config.errorHandler;
101
170
  app.config.errorHandler = (err, instance, info) => {
@@ -158,56 +227,6 @@ function useAllStakSpan(opts) {
158
227
  });
159
228
  return span;
160
229
  }
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
230
  var AllStakErrorBoundary = vue.defineComponent({
212
231
  name: "AllStakErrorBoundary",
213
232
  props: {
@@ -243,7 +262,7 @@ var AllStakErrorBoundary = vue.defineComponent({
243
262
  }
244
263
  });
245
264
  var SDK_NAME = "allstak-vue";
246
- var SDK_VERSION = "0.1.0";
265
+ var SDK_VERSION = "0.2.0";
247
266
 
248
267
  Object.defineProperty(exports, "AllStak", {
249
268
  enumerable: true,
package/dist/index.js.map CHANGED
@@ -1 +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"]}
1
+ {"version":3,"sources":["../src/init.ts","../src/tracing-mixin.ts","../src/router.ts","../src/plugin.ts","../src/composables.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 { AllStak } from '@allstak/js';\nimport type { Span } from '@allstak/js';\nimport type { Router } from 'vue-router';\n\n/**\n * Marker set on a router instance once its navigation guards are installed,\n * so manual and automatic instrumentation can't both register guards on the\n * same router. Shared with the plugin's auto-install path.\n */\nconst ROUTER_INSTRUMENTED = '__allstak_router_instrumented__';\n\n/**\n * Instrument vue-router so every route change opens a navigation span +\n * a breadcrumb.\n *\n * As of v0.2.0 the {@link AllStakPlugin} calls this automatically when it\n * can resolve a router (default-on, see `autoInstrumentRouter`), so most\n * apps no longer need to call it by hand. It remains exported for apps that\n * opt out of auto-instrumentation or want to wire a router the plugin can't\n * reach. Calling it more than once on the same router is a safe no-op.\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 // Idempotency guard: never double-register navigation guards on a router\n // that is already instrumented (manually or by the plugin's auto path).\n const marked = router as Router & { [ROUTER_INSTRUMENTED]?: boolean };\n if (marked[ROUTER_INSTRUMENTED]) return;\n marked[ROUTER_INSTRUMENTED] = true;\n\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 type { App, Plugin } from 'vue';\nimport { AllStak } from '@allstak/js';\nimport type { AllStakConfig } from '@allstak/js';\nimport type { Router } from 'vue-router';\nimport { init } from './init';\nimport { installComponentTracing } from './tracing-mixin';\nimport type { ComponentTracingOptions } from './tracing-mixin';\nimport { installRouterInstrumentation } from './router';\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 * Automatically instrument vue-router so every route change opens a\n * navigation span + breadcrumb — no manual `installRouterInstrumentation`\n * call required. Default: `true`.\n *\n * The plugin resolves the router from (in order):\n * 1. the explicit `router` option below, then\n * 2. `app.config.globalProperties.$router` (set by `app.use(router)`).\n *\n * When vue-router is not installed, no router is found, or you've already\n * instrumented the router yourself, this is a safe no-op. Set to `false`\n * to opt out entirely and wire the router instrumentation by hand.\n */\n autoInstrumentRouter?: boolean;\n\n /**\n * The vue-router instance to auto-instrument. Optional — when omitted the\n * plugin falls back to `app.config.globalProperties.$router`. Provide this\n * (or register the router with `app.use(router)` before\n * `app.use(AllStakPlugin)`) so navigation spans are captured automatically.\n */\n router?: Router;\n}\n\n/**\n * Resolve a vue-router instance and instrument it for navigation spans.\n *\n * Resolution order: the explicit `router` argument, then the router that\n * `app.use(router)` exposes on `app.config.globalProperties.$router`. When\n * neither yields a usable router (e.g. vue-router isn't installed) this is a\n * silent no-op. `installRouterInstrumentation` is itself idempotent, so it's\n * safe even if the same router is reached through more than one path or the\n * plugin is installed twice.\n */\nfunction autoInstallRouter(app: App, explicit?: Router): void {\n try {\n const candidate =\n explicit ?? (app.config.globalProperties.$router as Router | undefined);\n\n // Must look like a vue-router instance (navigation-guard surface present).\n if (\n !candidate ||\n typeof (candidate as { beforeEach?: unknown }).beforeEach !== 'function'\n ) {\n return;\n }\n\n installRouterInstrumentation(candidate);\n } catch {\n // Never let observability wiring break app startup.\n }\n}\n\n/**\n * Vue 3 plugin.\n *\n * import { createApp } from 'vue';\n * import { AllStakPlugin } from '@allstak/vue';\n * import { router } from './router';\n * import App from './App.vue';\n *\n * createApp(App)\n * .use(router) // register vue-router first, and …\n * .use(AllStakPlugin, { // … navigation spans are wired automatically.\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 *\n * If you install the plugin before the router (or want to be explicit),\n * pass it directly: `.use(AllStakPlugin, { apiKey, router })`.\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 autoInstrumentRouter = true,\n tracingOptions,\n router,\n ...config\n } = options;\n\n if (!skipInit) {\n init(config);\n }\n\n if (tracingOptions) {\n installComponentTracing(app, tracingOptions);\n }\n\n if (autoInstrumentRouter) {\n autoInstallRouter(app, router);\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 { 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 CHANGED
@@ -7,7 +7,7 @@ function init(config) {
7
7
  return AllStak.init({
8
8
  ...config,
9
9
  sdkName: config.sdkName ?? "allstak-vue",
10
- sdkVersion: config.sdkVersion ?? "0.1.0"
10
+ sdkVersion: config.sdkVersion ?? "0.2.0"
11
11
  });
12
12
  }
13
13
  var DEFAULT_HOOKS = ["mount"];
@@ -78,15 +78,81 @@ function installComponentTracing(app, options = {}) {
78
78
  if (Array.isArray(trackComponents) && trackComponents.length === 0) return;
79
79
  app.mixin(createTracingMixins(options));
80
80
  }
81
+ var ROUTER_INSTRUMENTED = "__allstak_router_instrumented__";
82
+ function installRouterInstrumentation(router) {
83
+ const marked = router;
84
+ if (marked[ROUTER_INSTRUMENTED]) return;
85
+ marked[ROUTER_INSTRUMENTED] = true;
86
+ let activeNavSpan = null;
87
+ router.beforeEach((to, from) => {
88
+ try {
89
+ AllStak.addBreadcrumb({
90
+ type: "navigation",
91
+ message: `${String(from.fullPath)} \u2192 ${String(to.fullPath)}`,
92
+ level: "info",
93
+ data: {
94
+ name: String(to.name ?? ""),
95
+ fullPath: to.fullPath,
96
+ params: to.params,
97
+ query: to.query
98
+ }
99
+ });
100
+ activeNavSpan = AllStak.startSpan("navigation", {
101
+ description: String(to.fullPath),
102
+ attributes: {
103
+ "allstak.origin": "auto.navigation.vue",
104
+ "route.name": String(to.name ?? ""),
105
+ "route.path": to.path
106
+ }
107
+ });
108
+ } catch {
109
+ }
110
+ });
111
+ router.afterEach(() => {
112
+ try {
113
+ activeNavSpan?.finish("ok");
114
+ } catch {
115
+ } finally {
116
+ activeNavSpan = null;
117
+ }
118
+ });
119
+ router.onError((err) => {
120
+ try {
121
+ activeNavSpan?.finish("error");
122
+ AllStak.captureException(err instanceof Error ? err : new Error(String(err)), {
123
+ framework: "vue",
124
+ source: "vue-router"
125
+ });
126
+ } catch {
127
+ } finally {
128
+ activeNavSpan = null;
129
+ }
130
+ });
131
+ }
132
+ function useAllStakRouter(router) {
133
+ return installRouterInstrumentation(router);
134
+ }
81
135
 
82
136
  // src/plugin.ts
137
+ function autoInstallRouter(app, explicit) {
138
+ try {
139
+ const candidate = explicit ?? app.config.globalProperties.$router;
140
+ if (!candidate || typeof candidate.beforeEach !== "function") {
141
+ return;
142
+ }
143
+ installRouterInstrumentation(candidate);
144
+ } catch {
145
+ }
146
+ }
83
147
  var AllStakPlugin = {
84
148
  install(app, options = {}) {
85
149
  const {
86
150
  attachErrorHandler = true,
87
151
  attachWarnHandler = false,
88
152
  skipInit = false,
153
+ autoInstrumentRouter = true,
89
154
  tracingOptions,
155
+ router,
90
156
  ...config
91
157
  } = options;
92
158
  if (!skipInit) {
@@ -95,6 +161,9 @@ var AllStakPlugin = {
95
161
  if (tracingOptions) {
96
162
  installComponentTracing(app, tracingOptions);
97
163
  }
164
+ if (autoInstrumentRouter) {
165
+ autoInstallRouter(app, router);
166
+ }
98
167
  if (attachErrorHandler) {
99
168
  const prev = app.config.errorHandler;
100
169
  app.config.errorHandler = (err, instance, info) => {
@@ -157,56 +226,6 @@ function useAllStakSpan(opts) {
157
226
  });
158
227
  return span;
159
228
  }
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
229
  var AllStakErrorBoundary = defineComponent({
211
230
  name: "AllStakErrorBoundary",
212
231
  props: {
@@ -242,7 +261,7 @@ var AllStakErrorBoundary = defineComponent({
242
261
  }
243
262
  });
244
263
  var SDK_NAME = "allstak-vue";
245
- var SDK_VERSION = "0.1.0";
264
+ var SDK_VERSION = "0.2.0";
246
265
 
247
266
  export { AllStakErrorBoundary, AllStakPlugin, SDK_NAME, SDK_VERSION, createTracingMixins, init, installComponentTracing, installRouterInstrumentation, useAllStak, useAllStakRouter, useAllStakSpan, useAllStakUser };
248
267
  //# sourceMappingURL=index.mjs.map
@@ -1 +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"],"mappings":"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","file":"index.mjs","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"]}
1
+ {"version":3,"sources":["../src/init.ts","../src/tracing-mixin.ts","../src/router.ts","../src/plugin.ts","../src/composables.ts","../src/error-boundary.ts","../src/index.ts"],"names":["AllStak"],"mappings":"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","file":"index.mjs","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 { AllStak } from '@allstak/js';\nimport type { Span } from '@allstak/js';\nimport type { Router } from 'vue-router';\n\n/**\n * Marker set on a router instance once its navigation guards are installed,\n * so manual and automatic instrumentation can't both register guards on the\n * same router. Shared with the plugin's auto-install path.\n */\nconst ROUTER_INSTRUMENTED = '__allstak_router_instrumented__';\n\n/**\n * Instrument vue-router so every route change opens a navigation span +\n * a breadcrumb.\n *\n * As of v0.2.0 the {@link AllStakPlugin} calls this automatically when it\n * can resolve a router (default-on, see `autoInstrumentRouter`), so most\n * apps no longer need to call it by hand. It remains exported for apps that\n * opt out of auto-instrumentation or want to wire a router the plugin can't\n * reach. Calling it more than once on the same router is a safe no-op.\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 // Idempotency guard: never double-register navigation guards on a router\n // that is already instrumented (manually or by the plugin's auto path).\n const marked = router as Router & { [ROUTER_INSTRUMENTED]?: boolean };\n if (marked[ROUTER_INSTRUMENTED]) return;\n marked[ROUTER_INSTRUMENTED] = true;\n\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 type { App, Plugin } from 'vue';\nimport { AllStak } from '@allstak/js';\nimport type { AllStakConfig } from '@allstak/js';\nimport type { Router } from 'vue-router';\nimport { init } from './init';\nimport { installComponentTracing } from './tracing-mixin';\nimport type { ComponentTracingOptions } from './tracing-mixin';\nimport { installRouterInstrumentation } from './router';\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 * Automatically instrument vue-router so every route change opens a\n * navigation span + breadcrumb — no manual `installRouterInstrumentation`\n * call required. Default: `true`.\n *\n * The plugin resolves the router from (in order):\n * 1. the explicit `router` option below, then\n * 2. `app.config.globalProperties.$router` (set by `app.use(router)`).\n *\n * When vue-router is not installed, no router is found, or you've already\n * instrumented the router yourself, this is a safe no-op. Set to `false`\n * to opt out entirely and wire the router instrumentation by hand.\n */\n autoInstrumentRouter?: boolean;\n\n /**\n * The vue-router instance to auto-instrument. Optional — when omitted the\n * plugin falls back to `app.config.globalProperties.$router`. Provide this\n * (or register the router with `app.use(router)` before\n * `app.use(AllStakPlugin)`) so navigation spans are captured automatically.\n */\n router?: Router;\n}\n\n/**\n * Resolve a vue-router instance and instrument it for navigation spans.\n *\n * Resolution order: the explicit `router` argument, then the router that\n * `app.use(router)` exposes on `app.config.globalProperties.$router`. When\n * neither yields a usable router (e.g. vue-router isn't installed) this is a\n * silent no-op. `installRouterInstrumentation` is itself idempotent, so it's\n * safe even if the same router is reached through more than one path or the\n * plugin is installed twice.\n */\nfunction autoInstallRouter(app: App, explicit?: Router): void {\n try {\n const candidate =\n explicit ?? (app.config.globalProperties.$router as Router | undefined);\n\n // Must look like a vue-router instance (navigation-guard surface present).\n if (\n !candidate ||\n typeof (candidate as { beforeEach?: unknown }).beforeEach !== 'function'\n ) {\n return;\n }\n\n installRouterInstrumentation(candidate);\n } catch {\n // Never let observability wiring break app startup.\n }\n}\n\n/**\n * Vue 3 plugin.\n *\n * import { createApp } from 'vue';\n * import { AllStakPlugin } from '@allstak/vue';\n * import { router } from './router';\n * import App from './App.vue';\n *\n * createApp(App)\n * .use(router) // register vue-router first, and …\n * .use(AllStakPlugin, { // … navigation spans are wired automatically.\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 *\n * If you install the plugin before the router (or want to be explicit),\n * pass it directly: `.use(AllStakPlugin, { apiKey, router })`.\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 autoInstrumentRouter = true,\n tracingOptions,\n router,\n ...config\n } = options;\n\n if (!skipInit) {\n init(config);\n }\n\n if (tracingOptions) {\n installComponentTracing(app, tracingOptions);\n }\n\n if (autoInstrumentRouter) {\n autoInstallRouter(app, router);\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 { 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allstak/vue",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Official AllStak SDK for Vue 3 — error tracking, structured logs, distributed tracing, and observability for Vue applications.",
5
5
  "keywords": [
6
6
  "vue",