0298224796f73db7d4d58c1beae41f121a54a54d
[ndcode_site.git] / _config / site.jst
1 let assert = require('assert')
2 let EmailJSCache = require('@ndcode/emailjs_cache')
3 let ZettairCache = require('@ndcode/zettair_cache')
4
5 return async (resources, root, prev_site) => {
6   let logjson = (await import('@ndcode/logjson')).default
7
8   let CustomSite = function(resources, root, options, prev_site) {
9     if (!this instanceof CustomSite)
10       throw Error('CustomSite is a constructor')
11     _jst_server.Site.call(this, resources, root, options, prev_site)
12
13     this.database = undefined
14     this.emailjs_cache = undefined
15     this.zettair_cache = undefined
16   }
17
18   CustomSite.prototype = Object.create(_jst_server.Site.prototype)
19
20   // called when the server starts or the site.jst file is modified
21   // in latter case it will carry over the previously created resource objects
22   CustomSite.prototype.start = async function() {
23     await _jst_server.Site.prototype.start.call(this)
24
25     assert(this.database === undefined)
26     this.database = await this.resources.ref(
27       'database',
28       async () => {
29         let database = new logjson.Database()
30         await database.open(this.root + '/database.logjson')
31         return database
32       }
33     )
34
35     assert(this.emailjs_cache === undefined)
36     this.emailjs_cache = await this.resources.ref(
37       'emailjs_cache',
38       async () => new EmailJSCache(true)
39     )
40
41     assert(this.zettair_cache === undefined)
42     this.zettair_cache = await this.resources.ref(
43       'zettair_cache',
44       async () => new ZettairCache(true)
45     )
46   }
47
48   // called when the server starts or the site.jst file is modified
49   // in latter case the start() method of the new CustomSite object is called
50   // first and then the stop() method of the old CustomSite object, so that the
51   // reference counting can keep the resource objects alive during changeover
52   CustomSite.prototype.stop = async function() {
53     await _jst_server.Site.prototype.stop.call(this)
54
55     assert(this.database !== undefined)
56     await this.resources.unref('database')
57
58     assert(this.emailjs_cache !== undefined)
59     await this.resources.unref('emailjs_cache')
60
61     assert(this.zettair_cache !== undefined)
62     await this.resources.unref('zettair_cache')
63   }
64
65   // called once per second, responsible for cache cleaning and flushing
66   CustomSite.prototype.kick = async function() {
67     await _jst_server.Site.prototype.kick.call(this)
68
69     assert(this.database !== undefined)
70     this.database.kick()
71
72     assert(this.emailjs_cache !== undefined)
73     this.emailjs_cache.kick()
74
75     assert(this.zettair_cache !== undefined)
76     this.zettair_cache.kick()
77   }
78
79   // retrieves a particular email account (loaded into an emailjs object)
80   CustomSite.prototype.get_emailjs = function(pathname) {
81     return /*await*/ this.emailjs_cache.get(this.root + pathname)
82   }
83
84   // retrieves a particular search index (node.js wrapper of a zettair object)
85   CustomSite.prototype.get_zettair = function(pathname) {
86     return /*await*/ this.zettair_cache.get(this.root + pathname)
87   }
88
89   // customize the file search/serving algorithm for this particular website
90   CustomSite.prototype.respond = async function(env) {
91     if (
92       env.parsed_url.pathname === '/node_modules' ||
93       env.parsed_url.pathname.slice(0, 14) === '/node_modules/' ||
94       env.parsed_url.pathname === '/package.json' ||
95       env.parsed_url.pathname === '/package-lock.json'
96     ) {
97       this.die(env, `banned file ${env.parsed_url.pathname}`)
98       return
99     }
100     return /*await*/ _jst_server.Site.prototype.respond.call(this, env)
101   }
102
103   return new CustomSite(
104     resources,
105     root,
106     {},
107     prev_site
108   )
109 }