126 lines
4.0 KiB
TypeScript
126 lines
4.0 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
|
|
/**
|
|
* Built-in routes controller for TypedServer
|
|
* Handles robots.txt, manifest.json, sitemap, feed, appversion
|
|
*/
|
|
@plugins.smartserve.Route('')
|
|
export class BuiltInRoutesController {
|
|
private options: {
|
|
domain?: string;
|
|
robots?: boolean;
|
|
manifest?: plugins.smartmanifest.SmartManifest;
|
|
sitemap?: boolean;
|
|
feed?: boolean;
|
|
appVersion?: string;
|
|
feedMetadata?: plugins.smartfeed.IFeedOptions;
|
|
articleGetterFunction?: () => Promise<plugins.tsclass.content.IArticle[]>;
|
|
blockWaybackMachine?: boolean;
|
|
getSitemapUrls: () => plugins.smartsitemap.IUrlInfo[];
|
|
};
|
|
|
|
constructor(options: typeof BuiltInRoutesController.prototype.options) {
|
|
this.options = options;
|
|
}
|
|
|
|
@plugins.smartserve.Get('/robots.txt')
|
|
async getRobots(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
|
if (!this.options.robots || !this.options.domain) {
|
|
throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
|
|
}
|
|
|
|
const robotsContent = [
|
|
'User-agent: *',
|
|
'Allow: /',
|
|
`Sitemap: https://${this.options.domain}/sitemap`,
|
|
];
|
|
|
|
if (this.options.blockWaybackMachine) {
|
|
robotsContent.push('', 'User-agent: ia_archiver', 'Disallow: /');
|
|
}
|
|
|
|
return new Response(robotsContent.join('\n'), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'text/plain' },
|
|
});
|
|
}
|
|
|
|
@plugins.smartserve.Get('/manifest.json')
|
|
async getManifest(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
|
if (!this.options.manifest) {
|
|
throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
|
|
}
|
|
|
|
return new Response(this.options.manifest.jsonString(), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
});
|
|
}
|
|
|
|
@plugins.smartserve.Get('/sitemap')
|
|
async getSitemap(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
|
if (!this.options.sitemap || !this.options.domain) {
|
|
throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
|
|
}
|
|
|
|
const smartsitemap = new plugins.smartsitemap.SmartSitemap();
|
|
const urls = this.options.getSitemapUrls();
|
|
const sitemapXml = await smartsitemap.createSitemapFromUrlInfoArray(urls);
|
|
|
|
return new Response(sitemapXml, {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/xml' },
|
|
});
|
|
}
|
|
|
|
@plugins.smartserve.Get('/sitemap-news')
|
|
async getSitemapNews(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
|
if (!this.options.sitemap || !this.options.domain || !this.options.articleGetterFunction) {
|
|
throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
|
|
}
|
|
|
|
const smartsitemap = new plugins.smartsitemap.SmartSitemap();
|
|
const articles = await this.options.articleGetterFunction();
|
|
const sitemapNewsXml = await smartsitemap.createSitemapNewsFromArticleArray(articles);
|
|
|
|
return new Response(sitemapNewsXml, {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/xml' },
|
|
});
|
|
}
|
|
|
|
@plugins.smartserve.Get('/feed')
|
|
async getFeed(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
|
if (!this.options.feed || !this.options.feedMetadata) {
|
|
throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
|
|
}
|
|
|
|
const smartfeed = new plugins.smartfeed.Smartfeed();
|
|
const articles = this.options.articleGetterFunction
|
|
? await this.options.articleGetterFunction()
|
|
: [];
|
|
|
|
const feedXml = await smartfeed.createFeedFromArticleArray(
|
|
this.options.feedMetadata,
|
|
articles
|
|
);
|
|
|
|
return new Response(feedXml, {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/atom+xml' },
|
|
});
|
|
}
|
|
|
|
@plugins.smartserve.Get('/appversion')
|
|
async getAppVersion(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
|
|
if (!this.options.appVersion) {
|
|
throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
|
|
}
|
|
|
|
return new Response(this.options.appVersion, {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'text/plain' },
|
|
});
|
|
}
|
|
}
|