@buoy-gg/vue 0.0.0-stage → 7.0.75

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/LICENSE ADDED
@@ -0,0 +1,58 @@
1
+ PROPRIETARY SOFTWARE LICENSE
2
+
3
+ Copyright (c) 2024-present Buoy. All rights reserved.
4
+
5
+ This software and its source code are proprietary and confidential.
6
+
7
+ NOTICE: This is NOT open source software. This software is licensed,
8
+ not sold, and is protected by copyright laws and international treaties.
9
+
10
+ TERMS AND CONDITIONS:
11
+
12
+ 1. LICENSE GRANT
13
+ Subject to the terms of this Agreement and payment of applicable fees,
14
+ Buoy grants you a limited, non-exclusive, non-transferable license
15
+ to use the compiled software packages in your applications.
16
+
17
+ 2. RESTRICTIONS
18
+ You may NOT:
19
+ - Copy, modify, or distribute the source code
20
+ - Reverse engineer, decompile, or disassemble the software
21
+ - Remove or alter any proprietary notices or labels
22
+ - Sublicense, rent, lease, or lend the software
23
+ - Use the software to create competing products
24
+ - Share access credentials with unauthorized parties
25
+
26
+ 3. OWNERSHIP
27
+ React Buoy retains all right, title, and interest in the software,
28
+ including all intellectual property rights. This license does not
29
+ grant you any rights to trademarks or service marks.
30
+
31
+ 4. TERMINATION
32
+ This license is effective until terminated. Your rights under this
33
+ license will terminate automatically without notice if you fail to
34
+ comply with any of its terms. Upon termination, you must cease all
35
+ use and destroy all copies of the software.
36
+
37
+ 5. DISCLAIMER OF WARRANTIES
38
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
39
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
41
+
42
+ 6. LIMITATION OF LIABILITY
43
+ IN NO EVENT SHALL BUOY BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
44
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
45
+ CONNECTION WITH THIS LICENSE OR THE USE OF THE SOFTWARE.
46
+
47
+ 7. GOVERNING LAW
48
+ This Agreement shall be governed by and construed in accordance with
49
+ the laws of the United States, without regard to its conflict of
50
+ law provisions.
51
+
52
+ For licensing inquiries and subscription information:
53
+ - Website: https://buoy.gg
54
+ - Email: AustinLovesWorking@gmail.com
55
+
56
+ Unauthorized reproduction or distribution of this software, or any
57
+ portion of it, may result in severe civil and criminal penalties,
58
+ and will be prosecuted to the maximum extent possible under the law.
package/README.md CHANGED
@@ -1,3 +1,102 @@
1
- # Temporary Holding Version
1
+ # Buoy for Vue and Nuxt
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Buoy runs in Vue 3.3 and up, built with Vite, as a beta.
4
+ It runs in Nuxt 4 too.
5
+ Your app stays all Vue.
6
+ Buoy uses React for its own screens and brings it along.
7
+ The full guide is the [Vue page](https://buoy.gg/buoy/latest/docs/web/vue).
8
+
9
+ ## Install and sign in
10
+
11
+ Run these from your app folder:
12
+
13
+ ```sh
14
+ npm install --save-dev @buoy-gg/core @buoy-gg/vue @buoy-gg/network
15
+ npx --package=@buoy-gg/core buoy login
16
+ ```
17
+
18
+ Add more tools the same way.
19
+ Use the same version for all Buoy packages.
20
+ `buoy login` writes `VITE_BUOY_KEY` to a file Git ignores.
21
+
22
+ ## Set up in Vue
23
+
24
+ Add the Vite plugin:
25
+
26
+ ```ts
27
+ // vite.config.ts
28
+ import vue from '@vitejs/plugin-vue';
29
+ import { buoy } from '@buoy-gg/core/vite';
30
+
31
+ export default defineConfig({ plugins: [vue(), buoy()] });
32
+ ```
33
+
34
+ Add the Buoy plugin to your app:
35
+
36
+ ```ts
37
+ import { buoy } from '@buoy-gg/vue';
38
+
39
+ createApp(App).use(router).use(pinia).use(buoy).mount('#app');
40
+ ```
41
+
42
+ That's all.
43
+ The Vite plugin finds your tools and adds the early hook.
44
+ It leaves Buoy out of prod builds.
45
+ `app.use(buoy)` reads your key and starts Buoy when your app mounts.
46
+ It finds Vue Router, Pinia and Vue Query by itself.
47
+ It stops Buoy when your app unmounts.
48
+
49
+ ## Set up in Nuxt
50
+
51
+ ```ts
52
+ // nuxt.config.ts
53
+ export default defineNuxtConfig({ modules: ['@buoy-gg/vue/nuxt'] });
54
+ ```
55
+
56
+ That's all.
57
+ Pass options with the `buoy` key, as plain data.
58
+ For options with functions, set `buoy: { setup: false }`.
59
+ Then call `nuxtApp.vueApp.use(buoy, options)` in your own client plugin.
60
+
61
+ ## Options
62
+
63
+ `app.use(buoy, options)` takes the same options as `mountBuoy` from `@buoy-gg/core/web`, plus these:
64
+
65
+ | Option | What it does |
66
+ |---|---|
67
+ | `load` | Loads app settings with Buoy. Use a dev check so prod drops the file |
68
+ | `modules` | Your own tool list, in place of the plugin's |
69
+ | `enableInRelease` | Starts Buoy in a release build too. Set `buoy({ enableInRelease: true })` as well |
70
+ | `onMount` | Called with the stop function once Buoy is up |
71
+ | `onDestroy` | Called when Buoy stops |
72
+
73
+ `startBuoy(options)` starts Buoy with no Vue app.
74
+ Pass `router`, `pinia` and `queryClient` yourself.
75
+
76
+ ## Pinia and refs
77
+
78
+ Pinia stores show in the Zustand tool by themselves.
79
+ To show a plain `ref` or `reactive`, wrap it:
80
+
81
+ ```ts
82
+ import { buoyVueRef } from '@buoy-gg/vue/pinia';
83
+
84
+ app.use(buoy, { zustandStores: { count: buoyVueRef(count) } });
85
+ ```
86
+
87
+ You can read and edit them in the tool.
88
+ An edit keeps the fields you did not change.
89
+
90
+ ## Entry points
91
+
92
+ | Import | Holds |
93
+ |---|---|
94
+ | `@buoy-gg/vue` | `buoy`, `startBuoy` |
95
+ | `@buoy-gg/vue/register` | The early hook. The Vite plugin adds it for you |
96
+ | `@buoy-gg/vue/router` | `connectBuoyRouter`, for a router link by hand |
97
+ | `@buoy-gg/vue/pinia` | `watchPiniaStores`, `buoyVueRef` |
98
+ | `@buoy-gg/vue/highlights` | `connectBuoyHighlights`, for Highlight by hand |
99
+ | `@buoy-gg/vue/nuxt` | The Nuxt module |
100
+
101
+ Each app entry has a `buoy-disabled` build that does nothing.
102
+ The Vite plugin picks it for prod builds.
@@ -0,0 +1,7 @@
1
+ import type { BuoyHighlightController, VueInstance } from '../highlights';
2
+ export declare function componentName(_instance: VueInstance): string;
3
+ export declare function hostElements(_instance: VueInstance): HTMLElement[];
4
+ export declare function connectBuoyHighlights(_controller: BuoyHighlightController): () => void;
5
+ export declare function elementComponentName(_element: Element): string | undefined;
6
+ export declare function elementComponentSource(_element: Element): undefined;
7
+ export declare function onVueRender(_listener?: (instance: VueInstance) => void): () => void;
@@ -0,0 +1 @@
1
+ function e(n){return"Anonymous"}function o(n){return[]}function t(n){return()=>{}}function u(n){}function r(n){}function c(n){return()=>{}}export{e as componentName,t as connectBuoyHighlights,u as elementComponentName,r as elementComponentSource,o as hostElements,c as onVueRender};
@@ -0,0 +1,10 @@
1
+ import type { BuoyOptions, BuoyVueApp } from '../index';
2
+ /** The buoy-disabled build condition keeps no loader and no tools. */
3
+ export declare const buoy: {
4
+ install(_app: BuoyVueApp, _options?: BuoyOptions): void;
5
+ };
6
+ export default buoy;
7
+ export declare function startBuoy(_options?: BuoyOptions): () => void;
8
+ export declare function isBuoyDevBuild(): boolean;
9
+ export declare function findQueryClient(_app: BuoyVueApp): unknown;
10
+ export declare function appLinks(_app: BuoyVueApp): Pick<BuoyOptions, 'router' | 'pinia' | 'queryClient'>;
@@ -0,0 +1 @@
1
+ var t={install(n,e={}){}},u=t;function a(n={}){return()=>{}}function s(){return false}function i(n){}function r(n){return{}}export{r as appLinks,t as buoy,u as default,i as findQueryClient,s as isBuoyDevBuild,a as startBuoy};
@@ -0,0 +1,5 @@
1
+ import type { BuoyPinia, BuoyPiniaStore, BuoyStoreApi } from '../pinia';
2
+ export declare function plainCopy<T>(value: T): T;
3
+ export declare function piniaStoreApi(_store: BuoyPiniaStore): BuoyStoreApi<Record<string, unknown>>;
4
+ export declare function watchPiniaStores(_pinia: BuoyPinia, _zustand: unknown): () => void;
5
+ export declare function buoyVueRef<T extends object>(_source: T): BuoyStoreApi<unknown>;
@@ -0,0 +1 @@
1
+ var e={getState:()=>({}),getInitialState:()=>({}),setState:()=>{},subscribe:()=>()=>{}};function n(t){return t}function a(t){return e}function i(t,u){return()=>{}}function r(t){return e}export{r as buoyVueRef,a as piniaStoreApi,n as plainCopy,i as watchPiniaStores};
@@ -0,0 +1,4 @@
1
+ /** Keep the early entry inert when the build has disabled Buoy. */
2
+ export declare function registerBrowserNetwork(_options?: {
3
+ enableInRelease?: boolean;
4
+ }): boolean;
@@ -0,0 +1 @@
1
+ function r(e={}){return false}export{r as registerBrowserNetwork};
@@ -0,0 +1,4 @@
1
+ import type { BuoyVueRouter } from '../router';
2
+ export declare function vueRouteTemplate(pattern: string): string;
3
+ export declare function vueRoutePaths(_router: Pick<BuoyVueRouter, 'getRoutes'>): string[];
4
+ export declare function connectBuoyRouter(_router: BuoyVueRouter): () => void;
@@ -0,0 +1 @@
1
+ function e(t){return t}function u(t){return[]}function n(t){return()=>{}}export{n as connectBuoyRouter,u as vueRoutePaths,e as vueRouteTemplate};
@@ -0,0 +1,87 @@
1
+ /** The parts of a Vue 3 component instance Highlight reads. All are Vue's own and may be missing. */
2
+ export interface VueInstance {
3
+ uid?: number;
4
+ type?: {
5
+ name?: string;
6
+ __name?: string;
7
+ __file?: string;
8
+ };
9
+ subTree?: VueVNode | null;
10
+ parent?: VueInstance | null;
11
+ isMounted?: boolean;
12
+ isUnmounted?: boolean;
13
+ isDeactivated?: boolean;
14
+ }
15
+ interface VueVNode {
16
+ el?: Node | null;
17
+ anchor?: Node | null;
18
+ type?: unknown;
19
+ children?: unknown;
20
+ component?: VueInstance | null;
21
+ target?: Element | null;
22
+ }
23
+ export interface VueRenderBatch {
24
+ host: HTMLElement;
25
+ name: string;
26
+ count: number;
27
+ }
28
+ export interface BuoyHighlightController {
29
+ isEnabled(): boolean;
30
+ subscribe(listener: (enabled: boolean) => void): () => void;
31
+ connectRenderSource(available: boolean): {
32
+ recordRenders(renders: VueRenderBatch[]): void;
33
+ disconnect(): void;
34
+ };
35
+ }
36
+ /** A component's display name: its `name`, the SFC name Vue sets in dev, or its file name. */
37
+ export declare function componentName(instance: VueInstance): string;
38
+ /**
39
+ * The elements a component put on the page, for its boxes. Elements only, and
40
+ * only ones still on the page. A fragment gives every element between its
41
+ * start and end markers. A Teleport gives what it moved to its target. A
42
+ * component whose root is another component gives that one's elements.
43
+ */
44
+ export declare function hostElements(instance: VueInstance, depth?: number): HTMLElement[];
45
+ /**
46
+ * Hear each real component render. Vue also sends "updated" when a slot
47
+ * runs, naming the component that wrote the slot even though it didn't
48
+ * render. A real render gives the component a new `subTree`, so an event that
49
+ * leaves it the same is skipped, as are events during a first mount. Each
50
+ * component's tree is noted from the first call on; the early hook calls
51
+ * this at once, so components made before Highlight turns on are known too.
52
+ */
53
+ export declare function onVueRender(listener?: (instance: VueInstance) => void): () => void;
54
+ /**
55
+ * Feed Vue updates to Highlight Updates. Vue tells its dev hook about each
56
+ * component it updated; Buoy counts those while Highlight is on, and finds
57
+ * the names and boxes in the next animation frame, after Vue has finished.
58
+ * Only real renders count (see onVueRender).
59
+ */
60
+ export declare function connectBuoyHighlights(controller: BuoyHighlightController): () => void;
61
+ /**
62
+ * The app component an element belongs to, for Buoy's screen tools
63
+ * (describeScreen, hitTest). In dev, Vue marks each element with the
64
+ * component that rendered it.
65
+ */
66
+ /**
67
+ * The component behind a page element and the components around it, with the
68
+ * file each one lives in. Vue sets `__file` on SFCs in dev builds. Same shape
69
+ * as Buoy's React component source; Vue has no line numbers to give.
70
+ */
71
+ /** One component in the chain, in the shape Buoy's component source tool returns. */
72
+ export interface VueComponentSourceEntry {
73
+ name: string;
74
+ source?: {
75
+ fileName: string;
76
+ };
77
+ memo: false;
78
+ forwardRef: false;
79
+ reason?: string;
80
+ }
81
+ export declare function elementComponentSource(element: Element): {
82
+ found: true;
83
+ component: VueComponentSourceEntry;
84
+ owners: VueComponentSourceEntry[];
85
+ } | undefined;
86
+ export declare function elementComponentName(element: Element): string | undefined;
87
+ export {};
@@ -0,0 +1 @@
1
+ var H=Symbol.for("buoy.vue.hook"),M=2500;function _(){let e=globalThis;return e[H]??={listeners:new Set,wrappers:new WeakMap,armed:false}}function g(e,t){for(let n of _().listeners)try{n(e,t)}catch(r){console.error("[Buoy]",r)}}function u(e){let{wrappers:t}=_(),n=t.get(e);if(n&&e.emit===n)return true;let r=e.emit,o=function(l,...i){return g(l,i),r?.apply(this??e,[l,...i])};try{Object.defineProperty(e,"emit",{configurable:true,enumerable:true,get:()=>o,set:l=>{l!==o&&(r=l)}})}catch{let l=e.on;if(typeof l!="function")return false;for(let i of["component:added","component:updated","component:removed","perf:start","perf:end","app:init","app:unmount"])l.call(e,i,(...s)=>g(i,s))}return t.set(e,o),true}function b(){let e=new Map;return{enabled:false,apps:[],events:e,on(t,n){return e.has(t)||e.set(t,[]),e.get(t).push(n),()=>this.off(t,n)},once(t,n){let r=(...o)=>{this.off(t,r),n(...o)};this.on(t,r)},off(t,n){let r=e.get(t),o=r?.indexOf(n)??-1;r&&o!==-1&&r.splice(o,1)},emit(t,...n){for(let r of[...e.get(t)??[]])r(...n)}}}function B(){return typeof window>"u"||!window.HTMLElement?false:!window.navigator?.userAgent?.includes("jsdom")}function D(){let e=globalThis,t=_(),n=e.__VUE_DEVTOOLS_GLOBAL_HOOK__;if(n){u(n),t.armed=true;return}if(t.armed)return;if(t.armed=true,!B()){let r=b();u(r),e.__VUE_DEVTOOLS_GLOBAL_HOOK__=r;return}(e.__VUE_DEVTOOLS_HOOK_REPLAY__||=[]).push(r=>{u(r)}),setTimeout(()=>{if(e.__VUE_DEVTOOLS_GLOBAL_HOOK__){u(e.__VUE_DEVTOOLS_GLOBAL_HOOK__);return}let r=b();u(r),e.__VUE_DEVTOOLS_GLOBAL_HOOK__=r;let o=e.__VUE_DEVTOOLS_HOOK_REPLAY__??[];e.__VUE_DEVTOOLS_HOOK_REPLAY__=[];for(let l of o)try{l(r)}catch(i){console.error("[Buoy]",i)}},M)}function K(e){D();let{listeners:t}=_();return t.add(e),()=>{t.delete(e)}}var m=new Set(["BaseTransition","Transition","TransitionGroup","KeepAlive","Suspense","Teleport"]);function f(e){let t=e.type??{};return t.name?t.name:t.__name?t.__name:t.__file?.split(/[\\/]/).pop()?.replace(/\.\w+$/,"")||"Anonymous"}var O=e=>typeof HTMLElement<"u"&&e instanceof HTMLElement&&e.isConnected;function U(e){return!!(e&&typeof e=="object"&&e.__isTeleport)}function h(e,t=0){let n=e.subTree;return!n||t>20?[]:w(n,t)}function w(e,t){if(e.component)return h(e.component,t+1);if(U(e.type))return(Array.isArray(e.children)?e.children:[]).flatMap(o=>w(o,t+1));let n=e.el;if(!n)return[];if(e.anchor&&e.anchor!==n){let o=[];for(let l=n;l&&o.length<20&&(O(l)&&o.push(l),l!==e.anchor);l=l.nextSibling);return o}if(O(n))return[n];let r=n.parentElement;return n.nodeType===3&&O(r)?[r]:[]}var y=new WeakMap,R=Symbol.for("buoy.vue.renders");function G(){let e=globalThis;return e[R]??={trees:new WeakMap,listeners:new Set,installed:false}}function v(e){let t=G();return t.installed||(t.installed=true,K((n,r)=>{if(n!=="component:added"&&n!=="component:updated")return;let o=r[3];if(!o||typeof o!="object"||r[0]?._instance?.type?.devtools?.hide)return;let l=o.subTree,i=t.trees.has(o),s=t.trees.get(o)!==l;if(t.trees.set(o,l),!(n==="component:added"||!o.isMounted||i&&!s))for(let c of t.listeners)c(o)})),e?(t.listeners.add(e),()=>{t.listeners.delete(e)}):()=>{}}function P(e){let t=y.get(e);if(!t){let o=e.connectRenderSource(true),l=new Map,i,s=e.isEnabled(),c=false,S=()=>{if(i=void 0,c||!s){l.clear();return}let a=new Map;for(let[p,E]of l){if(p.isUnmounted||p.isDeactivated)continue;let L=f(p);if(!m.has(L))for(let d of h(p)){let T=a.get(d);T?T.count+=E:a.set(d,{host:d,name:L,count:E})}}l.clear(),a.size&&o.recordRenders([...a.values()])},V=v(a=>{s&&(l.set(a,(l.get(a)??0)+1),i??=requestAnimationFrame(S))}),A=e.subscribe(a=>{s=a,a||l.clear()});t={users:0,stop:()=>{c=true,V(),A(),i!==void 0&&cancelAnimationFrame(i),l.clear(),o.disconnect()}},y.set(e,t)}t.users++;let n=false,r=t;return()=>{n||(n=true,--r.users===0&&(r.stop(),y.delete(e)))}}function C(e){let t;for(let r=e;r&&!t;r=r.parentElement)t=r.__vueParentComponent;let n=[];for(let r=0;t&&r<200&&n.length<7;r++,t=t.parent??void 0){let o=f(t);if(m.has(o)||!t.parent&&!t.type?.__file)continue;let l=t.type?.__file;n.push({name:o,...l?{source:{fileName:l}}:{reason:"It comes from a library, so it has no file in the app."},memo:false,forwardRef:false})}if(n.length)return{found:true,component:n[0],owners:n.slice(1)}}function k(e){for(let t=e;t;t=t.parentElement){let n=t.__vueParentComponent;for(;n&&m.has(f(n));)n=n.parent??void 0;if(n)return f(n)}}export{f as componentName,P as connectBuoyHighlights,k as elementComponentName,C as elementComponentSource,h as hostElements,v as onVueRender};
package/lib/index.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ /** A tool's browser module, as its `/web` entry exports it. */
2
+ type Modules = Record<string, unknown>;
3
+ /**
4
+ * Buoy's props, kept here so a Vue app's TypeScript never loads the React
5
+ * types behind @buoy-gg/core. The common ones are named; the rest of
6
+ * `FloatingDevTools`' props pass through as they are.
7
+ */
8
+ export interface BuoyMountOptions {
9
+ environment?: 'local' | 'dev' | 'qa' | 'staging' | 'prod';
10
+ userRole?: 'admin' | 'internal' | 'user';
11
+ /** Defaults to VITE_BUOY_KEY, which `buoy login` writes. */
12
+ licenseKey?: string;
13
+ /** The app's TanStack Query client. Found from VueQueryPlugin when left out. */
14
+ queryClient?: unknown;
15
+ /** Stores for the Zustand tool: vanilla Zustand stores, or buoyVueRef() wrappers. */
16
+ zustandStores?: Record<string, unknown>;
17
+ /** Custom tools made with createWebTool. */
18
+ apps?: unknown[];
19
+ requiredEnvVars?: unknown[];
20
+ requiredStorageKeys?: unknown[];
21
+ externalSync?: boolean | {
22
+ socketURL?: string;
23
+ deviceName?: string;
24
+ enableInRelease?: boolean;
25
+ };
26
+ sentryGetClient?: () => unknown;
27
+ [prop: string]: unknown;
28
+ }
29
+ export interface BuoyOptions extends BuoyMountOptions {
30
+ /** Start in a release build as well. App access rules still apply. */
31
+ enableInRelease?: boolean;
32
+ /** The tools to load. Defaults to every tool the buoy() Vite plugin found. */
33
+ modules?: Modules | (() => Promise<Modules>);
34
+ /** The app's Vue Router. Found on the app when Buoy is installed with app.use(). */
35
+ router?: unknown;
36
+ /** The app's Pinia. Found on the app when Buoy is installed with app.use(). */
37
+ pinia?: unknown;
38
+ /**
39
+ * Load app settings and links with Buoy, such as `apps` or `zustandStores`.
40
+ * Use a dev-only dynamic import here so a production build leaves them out.
41
+ */
42
+ load?: () => Promise<Omit<BuoyOptions, 'load' | 'enableInRelease'>>;
43
+ /** Called once Buoy is mounted. The stop function is safe to call twice. */
44
+ onMount?: (stop: () => void) => void;
45
+ /** Called when Buoy stops, to remove app hooks the loader added. */
46
+ onDestroy?: () => void;
47
+ }
48
+ /** Whether Buoy starts by default: the phone app's debug flag in a Capacitor shell, otherwise a dev build. */
49
+ export declare function isBuoyDevBuild(): boolean;
50
+ /**
51
+ * Mount Buoy with no Vue app. Pass `queryClient`, `router` and `pinia`
52
+ * yourself. Returns a stop function that is safe to call before Buoy has
53
+ * finished loading.
54
+ */
55
+ export declare function startBuoy(options?: BuoyOptions): () => void;
56
+ /** The parts of a Vue 3 app Buoy reads. `_context` and `_container` are Vue's own. */
57
+ export interface BuoyVueApp {
58
+ mount(...args: unknown[]): unknown;
59
+ unmount(...args: unknown[]): unknown;
60
+ onUnmount?: (fn: () => void) => void;
61
+ config: {
62
+ globalProperties: Record<string, unknown>;
63
+ };
64
+ _context?: {
65
+ provides?: Record<string | symbol, unknown>;
66
+ };
67
+ _container?: unknown;
68
+ }
69
+ /** The Query client the app provided: VueQueryPlugin puts it in provides, under a key the app may change. */
70
+ export declare function findQueryClient(app: BuoyVueApp): unknown;
71
+ /** The router, Pinia and Query client the app installed. Read after mount, so plugin order doesn't matter. */
72
+ export declare function appLinks(app: BuoyVueApp): Pick<BuoyOptions, 'router' | 'pinia' | 'queryClient'>;
73
+ /**
74
+ * Buoy for a Vue app: `createApp(App).use(buoy).mount('#app')`. It finds the
75
+ * app's router, Pinia and Vue Query client when the app mounts, so it can go
76
+ * anywhere in the `use` chain. It renders nothing in the app.
77
+ */
78
+ export declare const buoy: {
79
+ install(app: BuoyVueApp, options?: BuoyOptions): void;
80
+ };
81
+ export default buoy;
package/lib/index.mjs ADDED
@@ -0,0 +1 @@
1
+ function N(){try{return import.meta.env.VITE_BUOY_KEY||void 0}catch{return}}function B(){if(typeof window>"u")return false;let e=window.Capacitor,t=false;try{t=e?.isNativePlatform?.()===true}catch{t=false}return t?e?.DEBUG===true:typeof __DEV__<"u"?!!__DEV__:process.env.NODE_ENV!=="production"}function O(e={}){if(typeof window>"u"||typeof document>"u")return()=>{};let{enableInRelease:t,modules:o,router:n,pinia:c,onMount:p,onDestroy:r,load:l,...h}=e;if(!B()&&!t)return()=>{};let g=globalThis;g.__BUOY_FRAMEWORK__!=="nuxt"&&(g.__BUOY_FRAMEWORK__="vue");let i=false,_,s=[];r&&s.push(r);let v=()=>{for(let u of s.splice(0).reverse())try{u()}catch(a){console.error("[Buoy]",a)}},E=async u=>{let a=await u();typeof a=="function"&&(i?a():s.push(a))};(async()=>{let u=l?await l():{},{modules:a,onDestroy:w,onMount:k,router:S,pinia:Y,...$}=u;if(w){if(i){w();return}s.push(w)}if(i)return;let y={...h,...$},m=a??o,f=typeof m=="function"?await m():m??(await import("@buoy-gg/core/web/installed-tools")).installedTools;if(i)return;let R=f["highlight-updates"]?.HighlightUpdatesController;if(R){let{connectBuoyHighlights:x}=await import("@buoy-gg/vue/highlights");if(i)return;try{s.push(x(R))}catch(I){console.warn("[Buoy] Highlight Updates already has a render source, so Vue updates are not shown.",I)}}let d={router:S??n,pinia:Y??c};if(d.router&&f["route-events"]&&(await E(async()=>(await import("@buoy-gg/vue/router")).connectBuoyRouter(d.router)),i))return;let U={...y.zustandStores??{}};if(d.pinia&&f.zustand&&(await E(async()=>(await import("@buoy-gg/vue/pinia")).watchPiniaStores(d.pinia,f.zustand)),i))return;let{mountBuoy:q}=await import("@buoy-gg/core/web");if(i)return;let C=y.queryClient,D=y.licenseKey??N();_=q({...y,modules:f,...Object.keys(U).length?{zustandStores:U}:{},...C?{queryClient:C}:{},...D?{licenseKey:D}:{}}),p?.(b)})().catch(u=>{v(),console.error("[Buoy] Buoy did not start.",u)});function b(){if(i)return;i=true;let u=_;_=void 0,u?.(),v()}return b}function K(e){let t=e._context?.provides;if(t)for(let o of Reflect.ownKeys(t)){let n=t[o];if(n&&typeof n.getQueryCache=="function")return n}}function V(e){let t=e.config.globalProperties,o={};t.$router&&(o.router=t.$router),t.$pinia&&(o.pinia=t.$pinia);let n=K(e);return n&&(o.queryClient=n),o}var z=Symbol.for("buoy.vue.installed"),M={install(e,t={}){if(typeof window>"u"||!B()&&!t.enableInRelease)return;let o=e;if(o[z])return;o[z]=true;let n,c=()=>{if(n)return;let r=V(e);n=O({...r,...t})},p=()=>{let r=n;n=void 0,r?.()};if(e._container)c();else{let r=e.mount;e.mount=function(...l){let h=r.apply(this??e,l);return c(),h}}if(typeof e.onUnmount=="function")e.onUnmount(p);else{let r=e.unmount;e.unmount=function(...l){return p(),r.apply(this??e,l)}}}},P=M;export{V as appLinks,M as buoy,P as default,K as findQueryClient,B as isBuoyDevBuild,O as startBuoy};
@@ -0,0 +1 @@
1
+ import{defineNuxtPlugin as o,useRuntimeConfig as i}from"#app";import{buoy as p}from"@buoy-gg/vue";var s=o(e=>{let u=i().public.buoy??{};e.vueApp.use(p,{...u})});export{s as default};
package/lib/nuxt.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /** Options for `modules: [['@buoy-gg/vue/nuxt', { ... }]]` or the `buoy` key in nuxt.config. */
2
+ export interface BuoyNuxtOptions {
3
+ /** Keep Buoy in a production build. App access rules still apply. */
4
+ enableInRelease?: boolean;
5
+ /** Installed tools to leave out, by package name, such as `['tv-remote']`. */
6
+ exclude?: string[];
7
+ /** Props for Buoy, the same as `app.use(buoy, options)` takes. They must be plain data. */
8
+ options?: Record<string, unknown>;
9
+ /**
10
+ * Set to false to call `nuxtApp.vueApp.use(buoy, options)` in your own
11
+ * client plugin, for options that aren't plain data (a `load` function).
12
+ * The module still adds the Vite plugin and the early hook.
13
+ */
14
+ setup?: boolean;
15
+ }
16
+ /** The parts of a Nuxt instance the module uses. */
17
+ interface NuxtLike {
18
+ options: {
19
+ dev: boolean;
20
+ plugins: (string | {
21
+ src: string;
22
+ mode?: 'client' | 'server' | 'all';
23
+ })[];
24
+ runtimeConfig: {
25
+ public: Record<string, unknown>;
26
+ };
27
+ buoy?: BuoyNuxtOptions;
28
+ };
29
+ hook(name: 'vite:extendConfig', fn: (config: {
30
+ plugins?: unknown[];
31
+ }, env: {
32
+ isClient: boolean;
33
+ }) => void): void;
34
+ }
35
+ /**
36
+ * Buoy for Nuxt: `modules: ['@buoy-gg/vue/nuxt']`. In the browser build only,
37
+ * it adds the buoy() Vite plugin, puts Buoy's early hook on the first line of
38
+ * Nuxt's client entry (before Nuxt makes the Vue app), and adds a client
39
+ * plugin that runs `app.use(buoy)`. The server build gets none of it. In a
40
+ * production build, Buoy's imports resolve to their disabled builds unless
41
+ * `enableInRelease` is set.
42
+ */
43
+ export default function buoyNuxt(inline: BuoyNuxtOptions, nuxt: NuxtLike): void;
44
+ export {};
package/lib/nuxt.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import{buoy as u}from"@buoy-gg/core/vite";var r=/[\\/]nuxt[\\/]dist[\\/]app[\\/]entry(?:\.async)?\.js$/;function i(s={},e){let n={...e.options.buoy,...s},t=!!n.enableInRelease;if(!e.options.dev&&!t){e.hook("vite:extendConfig",o=>{o.plugins??=[],o.plugins.push(u({exclude:n.exclude,register:false}))});return}e.options.runtimeConfig.public.buoy={...n.options??{},...t?{enableInRelease:t}:{}},n.setup!==false&&e.options.plugins.push({src:new URL("./nuxt-plugin.mjs",import.meta.url).pathname,mode:"client"}),e.hook("vite:extendConfig",(o,{isClient:l})=>{l&&(o.plugins??=[],o.plugins.push(u({exclude:n.exclude,enableInRelease:t,register:false}),{name:"buoy-nuxt-early-hook",enforce:"pre",transform(a,p){if(r.test(p.split("?")[0]??""))return{code:`import '@buoy-gg/vue/register';
2
+ globalThis.__BUOY_FRAMEWORK__ = 'nuxt';
3
+ ${a}`,map:null}}}))})}i.meta={name:"@buoy-gg/vue/nuxt",configKey:"buoy"};export{i as default};
package/lib/pinia.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /** The parts of a Pinia store the bridge reads. */
2
+ export interface BuoyPiniaStore {
3
+ $id: string;
4
+ $state: Record<string, unknown>;
5
+ $patch(mutate: (state: Record<string, unknown>) => void): void;
6
+ $subscribe(callback: () => void, options?: {
7
+ detached?: boolean;
8
+ flush?: 'sync' | 'pre' | 'post';
9
+ }): () => void;
10
+ }
11
+ /** The parts of Pinia the store link reads. `_s` is Pinia's own map of live stores. */
12
+ export interface BuoyPinia {
13
+ _s: Map<string, BuoyPiniaStore>;
14
+ use(plugin: (context: {
15
+ store: BuoyPiniaStore;
16
+ }) => void): void;
17
+ }
18
+ /** What Buoy's Zustand tool reads and writes. */
19
+ export interface BuoyStoreApi<T> {
20
+ getState(): T;
21
+ getInitialState(): T;
22
+ setState(partial: Partial<T> | ((state: T) => Partial<T>), replace?: boolean): void;
23
+ subscribe(listener: (state: T, previous: T) => void): () => void;
24
+ }
25
+ /**
26
+ * A plain copy. Buoy keeps old states by reference, so it must never see the
27
+ * live store. Refs and reactive objects are unwrapped at every depth: a setup
28
+ * store keeps refs in its raw state, and `toRaw` alone only unwraps the top.
29
+ */
30
+ export declare function plainCopy<T>(value: T, seen?: WeakMap<object, unknown>): T;
31
+ /**
32
+ * One Pinia store as a store the Zustand tool can read and edit. The same
33
+ * contract as @buoy-gg/solid's store bridge: a read returns a plain copy,
34
+ * kept until the store changes; after a full replace, `getState()` returns
35
+ * the object handed in, which is how a Time Machine restore checks it took.
36
+ */
37
+ export declare function piniaStoreApi(store: BuoyPiniaStore): BuoyStoreApi<Record<string, unknown>>;
38
+ /**
39
+ * Show every Pinia store in the Zustand tool, by its id. Stores that exist
40
+ * now are added at once; Pinia makes the rest the first time the app uses
41
+ * them, and they are added then.
42
+ */
43
+ export declare function watchPiniaStores(pinia: BuoyPinia, zustand: unknown): () => void;
44
+ /** A `ref` or `reactive` as a store for the Zustand tool. A bare value shows as `{ value }`. */
45
+ export declare function buoyVueRef<T extends object>(source: T): BuoyStoreApi<unknown>;
package/lib/pinia.mjs ADDED
@@ -0,0 +1 @@
1
+ import{isRef as v,toRaw as $,watch as A}from"vue";function y(t,u=new WeakMap){let r=t;for(;v(r);)r=r.value;if(r===null||typeof r!="object")return r;let e=$(r);if(e instanceof Date)return new Date(e.getTime());if(u.has(e))return u.get(e);if(Array.isArray(e)){let n=[];u.set(e,n);for(let f of e)n.push(y(f,u));return n}let a={};u.set(e,a);for(let n of Object.keys(e))a[n]=y(e[n],u);return a}function d(t){let u=new Set,r=()=>y(t.$state),e=r(),a=e,n=false,f,i=(l,p)=>{for(let o of[...u])o(l,p)},w=()=>f?e:e=r(),g=()=>{f=t.$subscribe(()=>{if(n)return;let l=e;e=r(),i(e,l)},{detached:true,flush:"sync"})};return{getState:w,getInitialState:()=>a,setState(l,p){let o=w(),c=typeof l=="function"?l(o):l;if(c===null||typeof c!="object"||Array.isArray(c))return;let b=p?c:{...o,...c};n=true;try{t.$patch(h=>{for(let s of Object.keys(b))h[s]=y(b[s]);if(!p)return;let S=$(h);for(let s of Object.keys(S))s in b||(v(S[s])?h[s]=void 0:delete h[s])})}finally{n=false}let j=o;e=b,i(e,j)},subscribe(l){return u.add(l),f||g(),()=>{u.delete(l),u.size||(f?.(),f=void 0)}}}}function k(t,u){let r=u?.watchStores;if(typeof r!="function")return()=>{};let e=[],a=new WeakSet,n=true,f=i=>{!n||a.has(i)||(a.add(i),e.push(r({[i.$id]:Object.assign(d(i),{buoyLibrary:"pinia"})})))};for(let i of t._s.values())f(i);return t.use(({store:i})=>{f(i)}),()=>{if(n){n=false;for(let i of e.splice(0))i()}}}function O(t){let u=a=>a!==null&&typeof a=="object"&&!Array.isArray(a),r=v(t)&&!u($(t.value)),e={get $state(){return r?{value:t.value}:v(t)?t.value:t}};return d({$id:"ref",get $state(){return e.$state},$patch(a){if(r){let n={value:t.value};a(n),t.value=n.value;return}a(e.$state)},$subscribe:a=>A(t,a,{deep:true,flush:"sync"})})}export{O as buoyVueRef,d as piniaStoreApi,y as plainCopy,k as watchPiniaStores};
@@ -0,0 +1,2 @@
1
+ import '@buoy-gg/core/web/register-network';
2
+ export { registerBrowserNetwork } from '@buoy-gg/core/web/register-network';
@@ -0,0 +1 @@
1
+ import"@buoy-gg/core/web/register-network";var w=Symbol.for("buoy.vue.hook"),g=2500;function p(){let t=globalThis;return t[w]??={listeners:new Set,wrappers:new WeakMap,armed:false}}function d(t,e){for(let r of p().listeners)try{r(t,e)}catch(o){console.error("[Buoy]",o)}}function _(t){let{wrappers:e}=p(),r=e.get(t);if(r&&t.emit===r)return true;let o=t.emit,n=function(s,...i){return d(s,i),o?.apply(this??t,[s,...i])};try{Object.defineProperty(t,"emit",{configurable:true,enumerable:true,get:()=>n,set:s=>{s!==n&&(o=s)}})}catch{let s=t.on;if(typeof s!="function")return false;for(let i of["component:added","component:updated","component:removed","perf:start","perf:end","app:init","app:unmount"])s.call(t,i,(...a)=>d(i,a))}return e.set(t,n),true}function c(){let t=new Map;return{enabled:false,apps:[],events:t,on(e,r){return t.has(e)||t.set(e,[]),t.get(e).push(r),()=>this.off(e,r)},once(e,r){let o=(...n)=>{this.off(e,o),r(...n)};this.on(e,o)},off(e,r){let o=t.get(e),n=o?.indexOf(r)??-1;o&&n!==-1&&o.splice(n,1)},emit(e,...r){for(let o of[...t.get(e)??[]])o(...r)}}}function L(){return typeof window>"u"||!window.HTMLElement?false:!window.navigator?.userAgent?.includes("jsdom")}function O(){let t=globalThis,e=p(),r=t.__VUE_DEVTOOLS_GLOBAL_HOOK__;if(r){_(r),e.armed=true;return}if(e.armed)return;if(e.armed=true,!L()){let o=c();_(o),t.__VUE_DEVTOOLS_GLOBAL_HOOK__=o;return}(t.__VUE_DEVTOOLS_HOOK_REPLAY__||=[]).push(o=>{_(o)}),setTimeout(()=>{if(t.__VUE_DEVTOOLS_GLOBAL_HOOK__){_(t.__VUE_DEVTOOLS_GLOBAL_HOOK__);return}let o=c();_(o),t.__VUE_DEVTOOLS_GLOBAL_HOOK__=o;let n=t.__VUE_DEVTOOLS_HOOK_REPLAY__??[];t.__VUE_DEVTOOLS_HOOK_REPLAY__=[];for(let s of n)try{s(o)}catch(i){console.error("[Buoy]",i)}},g)}function h(t){O();let{listeners:e}=p();return e.add(t),()=>{e.delete(t)}}var y=new Set(["BaseTransition","Transition","TransitionGroup","KeepAlive","Suspense","Teleport"]);function m(t){let e=t.type??{};return e.name?e.name:e.__name?e.__name:e.__file?.split(/[\\/]/).pop()?.replace(/\.\w+$/,"")||"Anonymous"}var T=Symbol.for("buoy.vue.renders");function S(){let t=globalThis;return t[T]??={trees:new WeakMap,listeners:new Set,installed:false}}function b(t){let e=S();return e.installed||(e.installed=true,h((r,o)=>{if(r!=="component:added"&&r!=="component:updated")return;let n=o[3];if(!n||typeof n!="object"||o[0]?._instance?.type?.devtools?.hide)return;let s=n.subTree,i=e.trees.has(n),a=e.trees.get(n)!==s;if(e.trees.set(n,s),!(r==="component:added"||!n.isMounted||i&&!a))for(let f of e.listeners)f(n)})),t?(e.listeners.add(t),()=>{e.listeners.delete(t)}):()=>{}}function v(t){let e;for(let o=t;o&&!e;o=o.parentElement)e=o.__vueParentComponent;let r=[];for(let o=0;e&&o<200&&r.length<7;o++,e=e.parent??void 0){let n=m(e);if(y.has(n)||!e.parent&&!e.type?.__file)continue;let s=e.type?.__file;r.push({name:n,...s?{source:{fileName:s}}:{reason:"It comes from a library, so it has no file in the app."},memo:false,forwardRef:false})}if(r.length)return{found:true,component:r[0],owners:r.slice(1)}}function V(t){for(let e=t;e;e=e.parentElement){let r=e.__vueParentComponent;for(;r&&y.has(m(r));)r=r.parent??void 0;if(r)return m(r)}}var A=15;function M(){let t=null;return{isSupported:()=>true,start(){t?.();let e=new Map,r=0,o=false,n=(a,f)=>{let l=m(a),u=e.get(l)??{mount:0,updates:0};u[f]+=1,e.set(l,u),o||(o=true,r+=1,queueMicrotask(()=>{o=false}))},s=h((a,f)=>{let l=f[3];a==="component:added"&&l&&typeof l=="object"&&n(l,"mount")}),i=b(a=>n(a,"updates"));t=()=>{s(),i();let a=[...e].map(([l,u])=>({name:l,renders:u.mount+u.updates,totalMs:0,maxMs:0,avgMs:0,causes:{...u.mount?{mount:u.mount}:{},...u.updates?{hooks:u.updates}:{}}})),f={mount:0,hooks:0};for(let l of a)f.mount+=l.causes.mount??0,f.hooks+=l.causes.hooks??0;return{totalCommits:r,totalRenders:a.reduce((l,u)=>l+u.renders,0),capturedDurations:false,totalRenderMs:0,causes:f,topComponents:a.sort((l,u)=>u.renders-l.renders).slice(0,A)}}},stop(){let e=t;return t=null,e?e():null}}}import{registerBrowserNetwork as k}from"@buoy-gg/core/web/register-network";var E=globalThis;E.__BUOY_FRAMEWORK__!=="nuxt"&&(E.__BUOY_FRAMEWORK__="vue");O();b();globalThis[Symbol.for("buoy.dom.componentName")]=V;globalThis[Symbol.for("buoy.dom.componentSource")]=v;globalThis[Symbol.for("buoy.framework.renderCapture")]=M();export{k as registerBrowserNetwork};
@@ -0,0 +1,41 @@
1
+ /** The parts of a Vue Router location the Routes link reads. */
2
+ export interface BuoyVueRouteLocation {
3
+ path: string;
4
+ fullPath: string;
5
+ name?: string | symbol | null;
6
+ params: Record<string, string | string[] | undefined>;
7
+ query: Record<string, unknown>;
8
+ matched: {
9
+ path: string;
10
+ }[];
11
+ }
12
+ /** The parts of a Vue Router 4 or 5 instance the Routes link reads. */
13
+ export interface BuoyVueRouter {
14
+ afterEach(guard: (to: BuoyVueRouteLocation, from: BuoyVueRouteLocation, failure?: unknown) => unknown): () => void;
15
+ isReady(): Promise<unknown>;
16
+ currentRoute: {
17
+ value: BuoyVueRouteLocation;
18
+ };
19
+ getRoutes(): {
20
+ path: string;
21
+ children?: unknown[];
22
+ }[];
23
+ push(to: string): Promise<unknown>;
24
+ replace(to: string): Promise<unknown>;
25
+ back(): void;
26
+ addRoute?: (...args: never[]) => unknown;
27
+ removeRoute?: (...args: never[]) => unknown;
28
+ }
29
+ /**
30
+ * Vue Router paths in the Routes tool's form. `:id`, `:id?` and `:id(\\d+)`
31
+ * become `[id]`; repeatable `:id+` and `:id*` become `[...id]`.
32
+ */
33
+ export declare function vueRouteTemplate(pattern: string): string;
34
+ /** Every page path the router knows, as templates. Routes with only children are layouts, not pages. */
35
+ export declare function vueRoutePaths(router: Pick<BuoyVueRouter, 'getRoutes'>): string[];
36
+ /**
37
+ * Report Vue Router page changes to the Routes tool with their names and
38
+ * params, and let the tool's Go button and the MCP navigate through the
39
+ * router. Raw history capture stops adding its own events while this runs.
40
+ */
41
+ export declare function connectBuoyRouter(router: BuoyVueRouter): () => void;
package/lib/router.mjs ADDED
@@ -0,0 +1 @@
1
+ import{claimBrowserRouteEvents as $,registerBrowserRoutes as d,routeObserver as k}from"@buoy-gg/route-events/web";import{registerBrowserRouter as S}from"@buoy-gg/shared-ui/web/utils";function f(t){return`/${t}`.replace(/\/+/g,"/").replace(/(.)\/$/,"$1").replace(/:(\w+)(\((?:[^()]|\([^()]*\))*\))?([?+*])?/g,(a,r,n,s)=>s==="+"||s==="*"?`[...${r}]`:`[${r}]`)}function h(t){let a=t.getRoutes().filter(r=>!r.children?.length).map(r=>f(r.path));return[...new Set(a)]}function O(t){let a={};for(let[r,n]of Object.entries(t))Array.isArray(n)?a[r]=n.filter(s=>s!=null).map(String):n!=null&&(a[r]=String(n));return a}function E(t){let a=$(),r=d(h(t)),n=()=>{r(),r=d(h(t))},s=e=>{e.catch(()=>{})},b=S({push:e=>s(t.push(e)),replace:e=>s(t.replace(e)),back:()=>t.back(),canGoBack:()=>typeof history<"u"&&!!history.state?.back}),m=[];for(let e of["addRoute","removeRoute"]){let o=t[e];typeof o=="function"&&(t[e]=function(...l){let u=o.apply(this??t,l);return n(),u},m.push(()=>{t[e]=o}))}let g,i,v,c=true,y=e=>{if(!c||e.fullPath===v)return;v=e.fullPath;let o=e.matched[e.matched.length-1]?.path??e.path,l=f(o),u=O(e.query);for(let[P,R]of Object.entries(e.params))R!==void 0&&(u[P]=R);let B=typeof e.name=="string"?e.name:o,p=Date.now();k.emit({pathname:e.path,params:u,segments:l.split("/").filter(Boolean),routeName:B,matchedPath:o,previousPathname:g,timestamp:p,timeSincePrevious:i===void 0?void 0:p-i}),g=e.path,i=p},w=t.afterEach((e,o,l)=>{l||y(e)});return t.isReady().then(()=>y(t.currentRoute.value),()=>{}),()=>{if(c){c=false,w();for(let e of m.splice(0))e();r(),a(),b()}}}export{E as connectBuoyRouter,h as vueRoutePaths,f as vueRouteTemplate};
package/package.json CHANGED
@@ -1,6 +1,99 @@
1
1
  {
2
2
  "name": "@buoy-gg/vue",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "7.0.75",
4
+ "description": "Run Buoy in a Vue or Nuxt app.",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./lib/index.d.ts",
9
+ "buoy-disabled": "./lib/disabled/index.mjs",
10
+ "default": "./lib/index.mjs"
11
+ },
12
+ "./register": {
13
+ "types": "./lib/register.d.ts",
14
+ "buoy-disabled": "./lib/disabled/register.mjs",
15
+ "default": "./lib/register.mjs"
16
+ },
17
+ "./router": {
18
+ "types": "./lib/router.d.ts",
19
+ "buoy-disabled": "./lib/disabled/router.mjs",
20
+ "default": "./lib/router.mjs"
21
+ },
22
+ "./pinia": {
23
+ "types": "./lib/pinia.d.ts",
24
+ "buoy-disabled": "./lib/disabled/pinia.mjs",
25
+ "default": "./lib/pinia.mjs"
26
+ },
27
+ "./highlights": {
28
+ "types": "./lib/highlights.d.ts",
29
+ "buoy-disabled": "./lib/disabled/highlights.mjs",
30
+ "default": "./lib/highlights.mjs"
31
+ },
32
+ "./nuxt": {
33
+ "types": "./lib/nuxt.d.ts",
34
+ "default": "./lib/nuxt.mjs"
35
+ },
36
+ "./package.json": "./package.json"
37
+ },
38
+ "types": "./lib/index.d.ts",
39
+ "files": [
40
+ "lib",
41
+ "README.md"
42
+ ],
43
+ "sideEffects": [
44
+ "./lib/register.mjs",
45
+ "./lib/disabled/register.mjs"
46
+ ],
47
+ "dependencies": {
48
+ "react": "^19.2.0",
49
+ "react-dom": "^19.2.0",
50
+ "react-native-web": "^0.21.2",
51
+ "@buoy-gg/shared-ui": "^7.0.75",
52
+ "@buoy-gg/core": "^7.0.75"
53
+ },
54
+ "peerDependencies": {
55
+ "vue": ">=3.3 <4"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "vue-router": {
59
+ "optional": true
60
+ },
61
+ "pinia": {
62
+ "optional": true
63
+ },
64
+ "@tanstack/vue-query": {
65
+ "optional": true
66
+ },
67
+ "@tanstack/react-query": {
68
+ "optional": true
69
+ },
70
+ "@buoy-gg/route-events": {
71
+ "optional": true
72
+ },
73
+ "@buoy-gg/zustand": {
74
+ "optional": true
75
+ },
76
+ "@buoy-gg/highlight-updates": {
77
+ "optional": true
78
+ },
79
+ "nuxt": {
80
+ "optional": true
81
+ }
82
+ },
83
+ "devDependencies": {
84
+ "vue": "3.5.44",
85
+ "vue-router": "5.4.0",
86
+ "pinia": "4.1.0",
87
+ "@tanstack/vue-query": "5.104.5",
88
+ "esbuild": "^0.25.0",
89
+ "jsdom": "^26.1.0",
90
+ "typescript": "~5.8.3",
91
+ "vitest": "^3.2.0",
92
+ "@buoy-gg/zustand": "^7.0.75",
93
+ "@buoy-gg/route-events": "^7.0.75"
94
+ },
95
+ "scripts": {
96
+ "build": "node build.mjs && node ../../scripts/minify-lib.mjs && node ../../scripts/assert-minified.mjs",
97
+ "test": "vitest run --config vitest.config.mjs"
98
+ }
6
99
  }