feat(TypedServer): Integrate SmartServe controller routing; add built-in routes controller and refactor TypedServer to use controllers and FileServer
This commit is contained in:
125
ts/controllers/controller.builtin.ts
Normal file
125
ts/controllers/controller.builtin.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
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' },
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user