Advanced Features
Explore powerful features to take your application to the next level.
Plugin System
Extend PodStack with custom plugins:
// plugins/my-plugin.js
module.exports = {
name: 'my-plugin',
version: '1.0.0',
install(app, options) {
app.use((ctx, next) => {
ctx.custom = options.data
return next()
})
},
}
Register plugin in config:
// podstack.config.js
module.exports = {
plugins: [
{
plugin: require('./plugins/my-plugin'),
options: { data: 'custom-value' }
}
],
}
Middleware
Create custom middleware:
// middleware/auth.js
module.exports = async (ctx, next) => {
const token = ctx.headers.authorization?.split(' ')[1]
if (!token) {
ctx.status = 401
ctx.body = { error: 'Unauthorized' }
return
}
try {
ctx.user = verifyToken(token)
await next()
} catch (err) {
ctx.status = 403
ctx.body = { error: 'Invalid token' }
}
}
Webhooks
Set up webhooks for real-time events:
// Register webhook
app.post('/webhooks/user-created', (ctx) => {
const { userId, email } = ctx.request.body
// Process webhook event
console.log(`New user created: ${email}`)
ctx.status = 200
ctx.body = { success: true }
})
Trigger webhook:
async function triggerWebhook(event, data) {
const webhooks = await Webhook.find({ event })
for (const webhook of webhooks) {
await fetch(webhook.url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
}
}
Caching Strategies
Query Caching
async function getUser(id) {
const cacheKey = `user:${id}`
// Check cache first
let user = await cache.get(cacheKey)
if (user) return user
// Fetch from database
user = await User.findById(id)
// Store in cache for 1 hour
await cache.set(cacheKey, user, 3600)
return user
}
Cache Invalidation
async function updateUser(id, data) {
// Update database
const user = await User.update(id, data)
// Invalidate cache
await cache.delete(`user:${id}`)
return user
}
Background Jobs
Process long-running tasks asynchronously:
// Define job
const sendEmailJob = {
name: 'send-email',
async handler({ userId, email, subject }) {
await mailer.send({
to: email,
subject: subject,
template: 'welcome',
})
},
}
// Queue job
queue.enqueue('send-email', {
userId: 123,
email: 'user@example.com',
subject: 'Welcome!',
})
Custom Validators
// validators/email.js
module.exports = {
isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
},
async isUniqueEmail(email) {
const user = await User.findOne({ email })
return !user
},
}
Use validators:
const validators = require('./validators')
app.post('/api/users', async (ctx) => {
const { email } = ctx.request.body
if (!validators.isValidEmail(email)) {
ctx.status = 400
ctx.body = { error: 'Invalid email' }
return
}
if (!await validators.isUniqueEmail(email)) {
ctx.status = 409
ctx.body = { error: 'Email already exists' }
return
}
// Create user...
})
Pro Tip: Combine these features for powerful, scalable applications! ๐