“Use your tools to check MeteorJS documentation and show me a sample code for a validated method and a sample for a publication and subscription in React. Also add a comment for the Meteor version used.”
I use, like other millions of developers, the Context7 mcp.
Response :
Based on the MeteorJS documentation, here are sample code patterns for validated methods and publication/subscription in React.
Meteor Version: 3.4 (Current version used in your project)
1. Validated Method Sample
Using simpl-schema for Validation (Meteor 3.x)
// ===========================================
// File: imports/api/collections/posts/server/methods.js
// Meteor Version: 3.4
// ===========================================
import SimpleSchema from 'simpl-schema'
import { Meteor } from 'meteor/meteor'
import { Posts } from './collection'
// Method with inline validation
Meteor.methods({
'posts.create': async function ({ content, tags, visibility }) {
// Validate input using SimpleSchema
new SimpleSchema({
content: { type: String, max: 5000 },
tags: { type: Array, optional: true },
'tags.
Using mdg:validated-method Package (Alternative)
// ===========================================
// File: imports/api/collections/posts/methods.js
// Meteor Version: 3.4
// ===========================================
import { Meteor } from 'meteor/meteor'
import SimpleSchema from 'simpl-schema'
import { ValidatedMethod } from 'meteor/mdg:validated-method'
import { Posts } from './collection'
export const createPost = new ValidatedMethod({
name: 'posts.create',
validate: new SimpleSchema({
content: { type: String, max: 5000 },
tags: { type: Array, optional: true },
'tags.
2. Publication Sample
// ===========================================
// File: imports/api/collections/posts/server/publications.js
// Meteor Version: 3.4
// ===========================================
import { Meteor } from 'meteor/meteor'
import SimpleSchema from 'simpl-schema'
import { Posts } from './collection'
Meteor.publish('posts.user', function publishUserPosts({ userId, limit, skip }) {
// Validate arguments
new SimpleSchema({
userId: { type: String },
limit: { type: Number, min: 1, max: 100, defaultValue: 20 },
skip: { type: Number, min: 0, defaultValue: 0 }
}).validate({ userId, limit, skip })
// Security: filter by visibility
const selector = {
userId,
$or: [
{ visibility: 'public' },
{ userId: this.userId }
]
}
return Posts.find(selector, {
fields: { userId: 1, content: 1, tags: 1, visibility: 1, stats: 1, createdAt: 1 },
limit, skip, sort: { createdAt: -1 }
})
})
3. React Subscription Sample
// ===========================================
// File: imports/ui/pages/UserPosts.jsx
// Meteor Version: 3.4
// ===========================================
import React from 'react'
import { useSubscribe, useFind } from 'meteor/react-meteor-data'
import { Posts } from '../../api/collections/posts/collection'
import Loading from '../components/Loading'
import PostCard from '../components/PostCard'
function UserPosts({ userId }) {
// useSubscribe returns a function that indicates loading state
const isLoading = useSubscribe('posts.user', { userId, limit: 20, skip: 0 })
// useFind fetches data reactively from Minimongo
const posts = useFind(
() => Posts.find({ userId }, { sort: { createdAt: -1 } }),
[userId]
)
if (isLoading()) return <Loading />
return (
<div className="user-posts">
<h2>User Posts</h2>
{posts.length === 0 ? <p>No posts found.</p> : posts.map(post => <PostCard key={post._id} post={post} />)}
</div>
)
}
export default UserPosts
Calling Methods with Meteor.callAsync()
// ===========================================
// File: imports/ui/components/CreatePostForm.jsx
// Meteor Version: 3.4
// ===========================================
import React, { useState } from 'react'
import { Meteor } from 'meteor/meteor'
import Button from '@mui/material/Button'
import TextField from '@mui/material/TextField'
function CreatePostForm() {
const [content, setContent] = useState('')
const [submitting, setSubmitting] = useState(false)
const handleSubmit = async (e) => {
e.preventDefault()
setSubmitting(true)
try {
const postId = await Meteor.callAsync('posts.create', { content, visibility: 'public' })
console.log('Post created:', postId)
setContent('')
} catch (err) {
console.error('Error:', err.reason)
} finally {
setSubmitting(false)
}
}
return (
<form onSubmit={handleSubmit}>
<TextField value={content} onChange={(e) => setContent(e.target.value)} multiline rows={4} />
<Button type="submit" disabled={submitting || !content.trim()}>
{submitting ? 'Creating...' : 'Create Post'}
</Button>
</form>
)
}
Key Differences: Meteor 2.x vs 3.x
| Feature |
Meteor 2.x |
Meteor 3.x |
| Method calls |
Meteor.call() with callbacks |
Meteor.callAsync() with async/await |
| Database ops |
Collection.insert() |
Collection.insertAsync() |
| React hooks |
useTracker() |
useSubscribe(), useFind() |
| Loading state |
Boolean |
Function isLoading() |
visibility: {
type: String,
allowedValues: ['public', 'connections', 'private']
}
}).validate({ content, tags, visibility })
// Check authentication
if (!this.userId) {
throw new Meteor.Error(401, 'Not logged in',
'You must be logged in to create a post.')
}
// Perform database operation (async in Meteor 3.x)
const postId = await Posts.insertAsync({
userId: this.userId,
content,
tags: tags || [],
visibility: visibility || 'public',
stats: { likesCount: 0, commentsCount: 0, sharesCount: 0, viewsCount: 0 },
createdAt: new Date(),
updatedAt: new Date()
})
return postId
}
})
### Using `DISCOURSE_PLACEHOLDER_3` Package (Alternative)
DISCOURSE_PLACEHOLDER_4
---
## 2. Publication Sample
DISCOURSE_PLACEHOLDER_5
---
## 3. React Subscription Sample
DISCOURSE_PLACEHOLDER_6
### Calling Methods with `DISCOURSE_PLACEHOLDER_7`
DISCOURSE_PLACEHOLDER_8
---
## Key Differences: Meteor 2.x vs 3.x
|Feature|Meteor 2.x|Meteor 3.x|
| --- | --- | --- |
|Method calls|`DISCOURSE_PLACEHOLDER_9` with callbacks|`DISCOURSE_PLACEHOLDER_10` with async/await|
|Database ops|`DISCOURSE_PLACEHOLDER_11`|`DISCOURSE_PLACEHOLDER_12`|
|React hooks|`DISCOURSE_PLACEHOLDER_13`|`DISCOURSE_PLACEHOLDER_14`, `DISCOURSE_PLACEHOLDER_15`|
|Loading state|Boolean|Function `DISCOURSE_PLACEHOLDER_16`|: { type: String },
visibility: {
type: String,
allowedValues: ['public', 'connections', 'private'],
defaultValue: 'public'
}
}).validator(),
async run({ content, tags, visibility }) {
if (!this.userId) {
throw new Meteor.Error('posts.create.unauthorized', 'Must be logged in.')
}
return await Posts.insertAsync({ userId: this.userId, content, tags, visibility, createdAt: new Date() })
}
})
2. Publication Sample
DISCOURSE_PLACEHOLDER_5
3. React Subscription Sample
DISCOURSE_PLACEHOLDER_6
Calling Methods with DISCOURSE_PLACEHOLDER_7
DISCOURSE_PLACEHOLDER_8
Key Differences: Meteor 2.x vs 3.x
| Feature |
Meteor 2.x |
Meteor 3.x |
| Method calls |
DISCOURSE_PLACEHOLDER_9 with callbacks |
DISCOURSE_PLACEHOLDER_10 with async/await |
| Database ops |
DISCOURSE_PLACEHOLDER_11 |
DISCOURSE_PLACEHOLDER_12 |
| React hooks |
DISCOURSE_PLACEHOLDER_13 |
DISCOURSE_PLACEHOLDER_14, DISCOURSE_PLACEHOLDER_15 |
| Loading state |
Boolean |
Function DISCOURSE_PLACEHOLDER_16 |
visibility: {
type: String,
allowedValues: ['public', 'connections', 'private']
}
}).validate({ content, tags, visibility })
// Check authentication
if (!this.userId) {
throw new Meteor.Error(401, 'Not logged in',
'You must be logged in to create a post.')
}
// Perform database operation (async in Meteor 3.x)
const postId = await Posts.insertAsync({
userId: this.userId,
content,
tags: tags || [],
visibility: visibility || 'public',
stats: { likesCount: 0, commentsCount: 0, sharesCount: 0, viewsCount: 0 },
createdAt: new Date(),
updatedAt: new Date()
})
return postId
}
})
### Using `DISCOURSE_PLACEHOLDER_3` Package (Alternative)
DISCOURSE_PLACEHOLDER_4
---
## 2. Publication Sample
DISCOURSE_PLACEHOLDER_5
---
## 3. React Subscription Sample
DISCOURSE_PLACEHOLDER_6
### Calling Methods with `DISCOURSE_PLACEHOLDER_7`
DISCOURSE_PLACEHOLDER_8
---
## Key Differences: Meteor 2.x vs 3.x
|Feature|Meteor 2.x|Meteor 3.x|
| --- | --- | --- |
|Method calls|`DISCOURSE_PLACEHOLDER_9` with callbacks|`DISCOURSE_PLACEHOLDER_10` with async/await|
|Database ops|`DISCOURSE_PLACEHOLDER_11`|`DISCOURSE_PLACEHOLDER_12`|
|React hooks|`DISCOURSE_PLACEHOLDER_13`|`DISCOURSE_PLACEHOLDER_14`, `DISCOURSE_PLACEHOLDER_15`|
|Loading state|Boolean|Function `DISCOURSE_PLACEHOLDER_16`|