@nuxtjs/feed
Version:
Feed module enables everyone to have RSS, Atom and Json.
116 lines (94 loc) • 2.95 kB
JavaScript
const { join, resolve } = require('path')
const { promisify } = require('util')
const { writeFileSync } = require('fs')
const { Feed } = require('feed')
const AsyncCache = require('async-cache')
const logger = require('./logger')
const defaults = {
path: '/feed.xml',
async create (feed) {},
cacheTime: 1000 * 60 * 15
}
module.exports = async function (moduleOptions) {
const options = [
...await parseOptions(this.options.feed),
...await parseOptions(moduleOptions)
].map(o => ({ ...defaults, ...o }))
const feedCache = new AsyncCache({
load (feedIndex, callback) {
createFeed(options[feedIndex], callback).catch(err => logger.error(err))
}
})
feedCache.get = promisify(feedCache.get)
options.forEach((feedOptions, index) => {
this.nuxt.hook('generate:done', async () => {
if (index === 0) {
logger.info('Generating feeds')
}
const xmlGeneratePath = resolve(this.options.rootDir, join(this.options.generate.dir, feedOptions.path))
writeFileSync(xmlGeneratePath, await feedCache.get(index))
logger.success('Generated', feedOptions.path)
})
this.addServerMiddleware({
path: feedOptions.path,
async handler (req, res, next) {
try {
const xml = await feedCache.get(index)
res.setHeader('Content-Type', resolveContentType(feedOptions.type))
res.end(xml)
} catch (err) {
next(err)
}
}
})
})
}
async function parseOptions (options) {
// Factory function
if (typeof options === 'function') {
options = await options()
}
// Factory object
if (!Array.isArray(options)) {
if (options.factory) {
options = await options.factory(options.data)
}
}
// Check if is empty
if (Object.keys(options).length === 0) {
return []
}
// Single feed
if (!Array.isArray(options)) {
options = [options]
}
return options
}
function resolveContentType (type) {
const lookup = {
rss2: 'application/rss+xml',
atom1: 'application/atom+xml',
json1: 'application/json'
}
return (lookup.hasOwnProperty(type) ? lookup[type] : 'application/xml') + '; charset=UTF-8'
}
async function createFeed (feedOptions, callback) {
if (!['rss2', 'json1', 'atom1'].includes(feedOptions.type)) {
logger.fatal(`Could not create Feed ${feedOptions.path} - Unknown feed type`)
return callback(null, '', feedOptions.cacheTime)
}
const feed = new Feed()
try {
await feedOptions.create.call(this, feed, feedOptions.data)
feed.options = {
generator: 'https://github.com/nuxt-community/feed-module',
...feed.options
}
} catch (err) {
logger.error(err)
logger.fatal('Error while executing feed creation function')
return callback(null, '', feedOptions.cacheTime)
}
return callback(null, feed[feedOptions.type](), feedOptions.cacheTime)
}
module.exports.meta = require('../package.json')