1 let assert = require('assert')
2 let EmailJSCache = require('@ndcode/emailjs_cache')
3 let ZettairCache = require('@ndcode/zettair_cache')
5 return async (resources, root, prev_site) => {
6 let logjson = (await import('@ndcode/logjson')).default
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)
13 this.database = undefined
14 this.emailjs_cache = undefined
15 this.zettair_cache = undefined
18 CustomSite.prototype = Object.create(_jst_server.Site.prototype)
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)
25 assert(this.database === undefined)
26 this.database = await this.resources.ref(
29 let database = new logjson.Database()
30 await database.open(this.root + '/database.logjson')
35 assert(this.emailjs_cache === undefined)
36 this.emailjs_cache = await this.resources.ref(
38 async () => new EmailJSCache(true)
41 assert(this.zettair_cache === undefined)
42 this.zettair_cache = await this.resources.ref(
44 async () => new ZettairCache(true)
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)
55 assert(this.database !== undefined)
56 await this.resources.unref('database')
58 assert(this.emailjs_cache !== undefined)
59 await this.resources.unref('emailjs_cache')
61 assert(this.zettair_cache !== undefined)
62 await this.resources.unref('zettair_cache')
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)
69 assert(this.database !== undefined)
72 assert(this.emailjs_cache !== undefined)
73 this.emailjs_cache.kick()
75 assert(this.zettair_cache !== undefined)
76 this.zettair_cache.kick()
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)
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)
89 // customize the file search/serving algorithm for this particular website
90 CustomSite.prototype.respond = async function(env) {
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'
97 this.die(env, `banned file ${env.parsed_url.pathname}`)
100 return /*await*/ _jst_server.Site.prototype.respond.call(this, env)
103 return new CustomSite(