1 let assert = require('assert')
2 let logjson = (await import('@ndcode/logjson')).default
3 let EmailJSCache = require('@ndcode/emailjs_cache')
4 let XDate = require('xdate')
5 let ZettairCache = require('@ndcode/zettair_cache')
7 return async (resources, root, prev_site) => {
8 class CustomSite extends _jst_server.Site {
9 constructor(resources, root, options, prev_site) {
10 super(resources, root, options, prev_site)
11 this.database = undefined
12 this.database_date = new XDate().toUTCString('yyyyMMdd')
13 this.emailjs_cache = undefined
14 this.zettair_cache = undefined
17 // called when the server starts or the site.jst file is modified
18 // in latter case it will carry over the previously created resource objects
20 await _jst_server.Site.prototype.start.call(this)
22 assert(this.database === undefined)
23 this.database = await this.resources.ref(
26 let database = new logjson.Database()
27 await database.open(this.root + '/database.logjson')
32 assert(this.emailjs_cache === undefined)
33 this.emailjs_cache = await this.resources.ref(
35 async () => new EmailJSCache(true)
38 assert(this.zettair_cache === undefined)
39 this.zettair_cache = await this.resources.ref(
41 async () => new ZettairCache(true)
45 // called when the server starts or the site.jst file is modified
46 // in latter case the start() method of the new CustomSite object is called
47 // first and then the stop() method of the old CustomSite object, so that the
48 // reference counting can keep the resource objects alive during changeover
50 await _jst_server.Site.prototype.stop.call(this)
52 assert(this.database !== undefined)
53 await this.resources.unref('database')
55 assert(this.emailjs_cache !== undefined)
56 await this.resources.unref('emailjs_cache')
58 assert(this.zettair_cache !== undefined)
59 await this.resources.unref('zettair_cache')
62 // called once per second, responsible for cache cleaning and flushing
64 await _jst_server.Site.prototype.kick.call(this)
66 assert(this.database !== undefined)
67 await this.database.kick()
69 let new_database_date = new XDate().toUTCString('yyyyMMdd')
70 if (new_database_date !== this.database_date) {
77 await this.database.rotate(
78 `${this.root}/database.logjson.${this.database_date}`
80 this.database_date = new_database_date
83 assert(this.emailjs_cache !== undefined)
84 this.emailjs_cache.kick()
86 assert(this.zettair_cache !== undefined)
87 this.zettair_cache.kick()
90 // retrieves a particular email account (loaded into an emailjs object)
91 get_emailjs(pathname) {
92 return /*await*/ this.emailjs_cache.get(this.root + pathname)
95 // retrieves a particular search index (node.js wrapper of a zettair object)
96 get_zettair(pathname) {
97 return /*await*/ this.zettair_cache.get(this.root + pathname)
100 // customize the file search/serving algorithm for this particular website
103 env.parsed_url.pathname === '/node_modules' ||
104 env.parsed_url.pathname.slice(0, 14) === '/node_modules/' ||
105 env.parsed_url.pathname === '/package.json' ||
106 env.parsed_url.pathname === '/package-lock.json'
108 this.die(env, `banned file ${env.parsed_url.pathname}`)
111 return /*await*/ _jst_server.Site.prototype.respond.call(this, env)
115 return new CustomSite(