{"id":12529,"library":"vue-meteor-tracker","title":"Vue Meteor Tracker","description":"Vue Meteor Tracker is an integration library that seamlessly brings Meteor's powerful reactive data layer, based on `Tracker` computations, into Vue 3 and Vue 2.7+ applications. The current stable version is 2.0.0, which focuses on providing a more streamlined API compatible with modern Vue setups, including Vite. It allows developers to declare Meteor subscriptions and reactive data queries directly within Vue components' options API, ensuring that components automatically re-render when underlying Meteor collections or reactive sources change. A key differentiator is its automatic lifecycle management for Meteor subscriptions, stopping them when components are unmounted. This library simplifies building real-time UIs with Meteor and Vue by abstracting away manual Tracker computations and subscription management, offering a robust solution for reactive UIs in the Meteor ecosystem.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/Akryum/vue-meteor-integration","tags":["javascript","vue","meteor","integration","tracker","reactivity"],"install":[{"cmd":"npm install vue-meteor-tracker","lang":"bash","label":"npm"},{"cmd":"yarn add vue-meteor-tracker","lang":"bash","label":"yarn"},{"cmd":"pnpm add vue-meteor-tracker","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for Vue.js applications.","package":"vue","optional":false},{"reason":"Recommended bundler for modern Meteor projects, as per installation instructions.","package":"vite:bundler","optional":false}],"imports":[{"note":"This is the main plugin to install with `app.use(VueMeteor)`.","wrong":"const VueMeteor = require('vue-meteor-tracker')","symbol":"VueMeteor","correct":"import { VueMeteor } from 'vue-meteor-tracker'"},{"note":"Used to customize global Vue Meteor Tracker options, such as the default subscription function.","wrong":"import config from 'vue-meteor-tracker'","symbol":"config","correct":"import { config } from 'vue-meteor-tracker'"},{"note":"Reactivity is primarily managed via the `meteor` option in Vue components, not by directly assigning to `this.$meteor`.","wrong":"this.$meteor = { /* ... */ }","symbol":"Component Options API","correct":"export default {\n  meteor: {\n    $subscribe: { /* ... */ },\n    myReactiveData() { /* ... */ }\n  }\n}"}],"quickstart":{"code":"import { createApp } from 'vue';\nimport App from './App.vue';\nimport { VueMeteor } from 'vue-meteor-tracker';\n\n// Mock Meteor for standalone demonstration if not in a Meteor environment.\n// In a real Meteor app, `Meteor` and `Mongo.Collection` are globally available.\ndeclare global {\n  namespace Meteor {\n    const subscribe: (name: string, ...args: any[]) => { ready: () => boolean };\n    const Collection: new (name: string) => { find: (query?: any) => { fetch: () => any[] }, findOne: (query?: any) => any };\n  }\n}\n\nif (typeof (globalThis as any).Meteor === 'undefined') {\n  (globalThis as any).Meteor = {\n    subscribe: (name: string, ...args: any[]) => {\n      console.log(`Mock Meteor: Subscribing to ${name} with params: ${JSON.stringify(args)}`);\n      return { ready: () => true }; // Always ready for mock\n    },\n    Collection: function(name: string) {\n      console.log(`Mock Meteor: Creating Collection ${name}`);\n      const data: any[] = [];\n      if (name === 'Notes') {\n        data.push({ _id: 'note1', text: 'First Note' });\n        data.push({ _id: 'note2', text: 'Second Note' });\n      }\n      if (name === 'Threads') {\n        data.push({ _id: 'thread1', title: 'Main Thread' });\n      }\n      return {\n        find: (query?: any) => ({ fetch: () => data }),\n        findOne: (query?: any) => data.find(item => Object.keys(query).every(key => item[key] === query[key])) || null\n      };\n    } as any\n  };\n}\n\n// Example Vue component (App.vue)\nimport { defineComponent, ref } from 'vue';\n\nconst Notes = (globalThis as any).Meteor.Collection('Notes');\nconst Threads = (globalThis as any).Meteor.Collection('Threads');\n\nconst AppVueComponent = defineComponent({\n  name: 'MeteorTrackerExample',\n  data() {\n    return {\n      selectedThreadId: 'thread1',\n      myReactiveParam: 'paramValue',\n    };\n  },\n  meteor: {\n    $subscribe: {\n      'notesSubscription': () => [],\n      'threadsSubscription': function() {\n        return [this.selectedThreadId];\n      },\n    },\n    notes: function() {\n      return Notes.find({}).fetch();\n    },\n    selectedThread: function() {\n      return Threads.findOne({ _id: this.selectedThreadId });\n    },\n  },\n  mounted() {\n    console.log('Component mounted. Initial notes:', this.notes);\n    this.$subscribe('anotherSub', ['arg1', this.myReactiveParam]);\n  },\n  template: `\n    <div>\n      <h1>Vue Meteor Tracker Example</h1>\n      <p v-if=\"!$subReady.notesSubscription\">Loading notes...</p>\n      <div v-else>\n        <h2>Notes:</h2>\n        <ul>\n          <li v-for=\"note in notes\" :key=\"note._id\">{{ note.text }}</li>\n        </ul>\n      </div>\n\n      <p v-if=\"!$subReady.threadsSubscription\">Loading thread...</p>\n      <div v-else>\n        <h2>Selected Thread:</h2>\n        <p v-if=\"selectedThread\">{{ selectedThread.title }} (ID: {{ selectedThread._id }})</p>\n        <p v-else>No thread selected or found.</p>\n      </div>\n\n      <button @click=\"selectedThreadId = 'newThreadId'\">Change Thread ID (mock)</button>\n      <p>Subscription 'anotherSub' ready: {{ $subReady.anotherSub }}</p>\n    </div>\n  `,\n});\n\nconst app = createApp(AppVueComponent);\napp.use(VueMeteor);\napp.mount('#app');","lang":"typescript","description":"This quickstart demonstrates how to install `vue-meteor-tracker`, integrate it into a Vue application using `app.use(VueMeteor)`, and define reactive Meteor subscriptions and data queries within a Vue component's `meteor` option, automatically reacting to changes."},"warnings":[{"fix":"Refactor your subscriptions to be nested under `$subscribe` within the `meteor` option: `meteor: { $subscribe: { 'my-sub': [] } }`.","message":"In `v2.0.0-beta.3`, the `meteor: { subscribe: { ... } }` (without the `$` sign) option no longer functions as a subscription declaration and is instead treated as a regular data prop. Subscriptions must now be placed under the `$subscribe` key.","severity":"breaking","affected_versions":">=2.0.0-beta.3"},{"fix":"Update `this.$subscribe('name', 1, 2, 3)` to `this.$subscribe('name', [1, 2, 3])` or for reactive parameters: `this.$subscribe('name', () => [this.param1, this.param2])`.","message":"In `v2.0.0-beta.3`, the arguments for `this.$subscribe` have changed. Instead of variadic parameters, it now expects the publication name as a string and parameters as a single array or a function returning an array.","severity":"breaking","affected_versions":">=2.0.0-beta.3"},{"fix":"Ensure all keys used within the `meteor` option are unique across your component's options (e.g., `data`, `props`). Rename conflicting keys.","message":"In `v2.0.0-beta.2`, an error is thrown if a key defined in the `meteor` option for reactive data already exists in `data`, `props`, `methods`, or `computed` options.","severity":"breaking","affected_versions":">=2.0.0-beta.2"},{"fix":"Refactor your `meteor` data properties. Instead of `{ params() { ... }, update() { ... } }`, use a single function: `myProp() { return Threads.findOne({ _id: this.selectedThreadId }); }`.","message":"In `v2.0.0-beta.1`, data properties within the `meteor` option can now only be functions that directly return the reactive result. The previous `params` and `update` object structure is no longer supported.","severity":"breaking","affected_versions":">=2.0.0-beta.1"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `app.use(VueMeteor)` is called early in your application's bootstrap. If calling `$subscribe` or accessing `$subReady` programmatically, ensure it's within an appropriate component lifecycle hook like `mounted()`.","cause":"The `VueMeteor` plugin was not properly installed (`app.use(VueMeteor)`), or an attempt to access `$subReady` occurred before the component was fully initialized.","error":"TypeError: Cannot read properties of undefined (reading '$subReady')"},{"fix":"Rename the conflicting key in either your `meteor` option or the other component options (e.g., `data`, `props`) to ensure uniqueness.","cause":"A property name used within the `meteor` option (for reactive data) conflicts with an existing property in `data`, `props`, `methods`, or `computed` options (v2.0.0-beta.2 and later).","error":"Error: [vue-meteor-tracker] The key 'myProp' in the meteor option is already defined in data, props, methods, etc. Please use a unique key."},{"fix":"Ensure subscriptions are defined within the `meteor: { $subscribe: { ... } }` object. When calling `this.$subscribe`, pass parameters as an array: `this.$subscribe('my-sub', [1, 2, 3])` or as a function returning an array: `this.$subscribe('my-sub', () => [this.param])`.","cause":"Incorrectly defining a subscription under the main `meteor` object instead of the `$subscribe` object, or passing `this.$subscribe` parameters as separate arguments instead of an array (v2.0.0-beta.3 and later).","error":"Subscription 'mySubscription' is not ready (i.e., this.$subReady.mySubscription is unexpectedly false) when using `meteor` option for subscriptions."},{"fix":"Refactor your `meteor` data property from `{ params() { ... }, update() { ... } }` to a single function that directly returns the reactive result: `myProp() { return Threads.findOne({ _id: this.selectedThreadId }); }`.","cause":"Attempting to use the `params` and `update` object structure for `meteor` data properties, which was removed in v2.0.0-beta.1.","error":"TypeError: (0, _threads_collection.Threads.findOne) is not a function"}],"ecosystem":"npm"}