Move Server.get_XXX() functions to SiteRoot.internal_get_XXX(), make _site available...
authorNick Downing <nick@ndcode.org>
Sun, 18 Nov 2018 02:06:12 +0000 (13:06 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 18 Nov 2018 02:07:17 +0000 (13:07 +1100)
Server.js
SiteRoot.js
site/index.html.jst

index 80ec9db..208c9f8 100644 (file)
--- a/Server.js
+++ b/Server.js
@@ -1,68 +1,11 @@
-let BuildCache = require('@ndcode/build_cache')
-let CleanCSS = require('@ndcode/clean-css')
-let JSONCache = require('@ndcode/json_cache')
 let Site = require('./Site')
-let SVGO = require('svgo')
 let assert = require('assert')
-let disk_build = require('@ndcode/disk_build')
-let emailjs = require('emailjs')
 let fs = require('fs')
-let html_minifier = require('html-minifier')
 let jst = require('@ndcode/jst')
-let less = require('less/lib/less-node')
-let path = require('path')
-var stream_buffers = require('stream-buffers')
-let uglify_es = require('uglify-es')
 let url = require('url')
 let util = require('util')
-let yauzl = require('yauzl')
-let zetjs = require('zetjs')
 
-let fs_mkdir = util.promisify(fs.mkdir)
 let fs_readFile = util.promisify(fs.readFile)
-let fs_writeFile = util.promisify(fs.writeFile)
-let yauzl_open = util.promisify(yauzl.open)
-let clean_css = new CleanCSS({returnPromise: true})
-let svgo = new SVGO(
-  {
-    plugins: [
-      {cleanupAttrs: true},
-      {removeDoctype: true},
-      {removeXMLProcInst: true},
-      {removeComments: true},
-      {removeMetadata: true},
-      {removeTitle: true},
-      {removeDesc: true},
-      {removeUselessDefs: true},
-      {removeEditorsNSData: true},
-      {removeEmptyAttrs: true},
-      {removeHiddenElems: true},
-      {removeEmptyText: true},
-      {removeEmptyContainers: true},
-      {removeViewBox: false},
-      {cleanupEnableBackground: true},
-      {convertStyleToAttrs: true},
-      {convertColors: true},
-      {convertPathData: true},
-      {convertTransform: true},
-      {removeUnknownsAndDefaults: true},
-      {removeNonInheritableGroupAttrs: true},
-      {removeUselessStrokeAndFill: true},
-      {removeUnusedNS: true},
-      {cleanupIDs: true},
-      {cleanupNumericValues: true},
-      {moveElemsAttrsToGroup: true},
-      {moveGroupAttrsToElems: true},
-      {collapseGroups: true},
-      {removeRasterImages: false},
-      {mergePaths: true},
-      {convertShapeToPath: true},
-      {sortAttrs: true},
-      {removeDimensions: true}//,
-      //{removeAttrs: {attrs: '(stroke|fill)'}}
-    ]
-  }
-)
 
 let Server = function() {
   if (!this instanceof Server)
@@ -73,404 +16,10 @@ let Server = function() {
   this.mime_types = {}
   this.sites = {}
 
-  this.build_cache_email = new BuildCache()
-  this.build_cache_json = new BuildCache()
-  this.build_cache_css_less = new BuildCache()
-  this.build_cache_css_min = new BuildCache()
-  this.build_cache_html_min = new BuildCache()
-  this.build_cache_js_min = new BuildCache()
-  this.build_cache_svg_min = new BuildCache()
-  this.build_cache_text = new BuildCache()
-  this.build_cache_zet = new BuildCache()
-  this.build_cache_zip = new BuildCache()
-  this.json_cache = new JSONCache(true)
-
   this.mime_type_html = 'text/html; charset=utf-8'
   this.mime_type_default = 'application/octet-stream'
 }
 
-Server.prototype.get_email = function(pathname) {
-  return /*await*/ this.build_cache_email.get(
-    pathname,
-    async result => {
-      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-      console.log('getting', pathname, 'as email')
-      result.value = emailjs.server.connect(JSON.parse(text))
-    }
-  )
-}
-
-// this is for read-only JSON files
-// they will be reloaded from disk if modified
-Server.prototype.get_json = function(pathname) {
-  return /*await*/ this.build_cache_json.get(
-    pathname,
-    async result => {
-      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-      console.log('getting', pathname, 'as json')
-      result.value = JSON.parse(text)
-    }
-  )
-}
-
-Server.prototype.get_jst = function(pathname, root) {
-  return /*await*/ jst(pathname, root, {_server: this})
-}
-
-Server.prototype.get_css_less = function(pathname, root) {
-  let dirname = path.posix.dirname(pathname)
-  return /*await*/ this.build_cache_css_less.get(
-    pathname,
-    async result => {
-      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-      console.log('getting', pathname, 'as css_less')
-      let render = await less.render(
-        text,
-        {
-          //color: true,
-          //compress: false,
-          //depends: false,
-          filename: pathname,
-          //globalVars: null,
-          //ieCompat: false,
-          //insecure: false,
-          //javascriptEnabled: false,
-          //lint: false,
-          //math: 0,
-          //modifyVars: null,
-          pathnames: [dirname],
-          //plugins: [],
-          //reUsePluginManager: true,
-          //rewriteUrls: false,
-          rootpathname: root//,
-          //strictImports: false,
-          //strictUnits: false,
-          //urlArgs: ''
-        }
-      )
-      result.deps.concat(render.imports)
-      result.value = Buffer.from(render.css)
-    }
-  )
-}
-
-Server.prototype.get_css_min = function(pathname) {
-  return /*await*/ this.build_cache_css_min.get(
-    pathname,
-    async result => {
-      result.value = fs_readFile(
-        await disk_build(
-          pathname,
-          async built_pathname => {
-            console.log('getting', pathname, 'as css_min')
-            let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-            console.log('building', built_pathname)
-            let render = await clean_css.minify(text)
-            for (let i = 0; i < render.warnings.length; ++i)
-              console.log(`clean-css warning: ${render.warnings[i]}`)
-            return /*await*/ fs_writeFile(
-              built_pathname,
-              render.styles,
-              {encoding: 'utf-8'}
-            )
-          }
-        )
-      )
-    }
-  )
-}
-
-Server.prototype.get_html_min = function(pathname) {
-  return /*await*/ this.build_cache_html_min.get(
-    pathname,
-    async result => {
-      result.value = fs_readFile(
-        await disk_build(
-          pathname,
-          async built_pathname => {
-            console.log('getting', pathname, 'as html_min')
-            let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-            console.log('building', built_pathname)
-            return /*await*/ fs_writeFile(
-              built_pathname,
-              html_minifier.minify(text, {collapseWhitespace: true}),
-              {encoding: 'utf-8'}
-            )
-          }
-        )
-      )
-    }
-  )
-}
-
-Server.prototype.get_js_min = function(pathname) {
-  return /*await*/ this.build_cache_js_min.get(
-    pathname,
-    async result => {
-      result.value = fs_readFile(
-        await disk_build(
-          pathname,
-          async built_pathname => {
-            console.log('getting', pathname, 'as js_min')
-            let files = {}
-            files[pathname] = await fs_readFile(pathname, {encoding: 'utf-8'})
-            console.log('building', built_pathname)
-            let render = uglify_es.minify(
-              files,
-              {
-                //compress: {
-                  //arrows        : true,
-                  //booleans      : true,
-                  //collapse_vars : true,
-                  //comparisons   : true,
-                  //computed_props: true,
-                  //conditionals  : true,
-                  //dead_code     : true,
-                  //drop_console  : false,
-                  //drop_debugger : true,
-                  //ecma          : 5,
-                  //evaluate      : true,
-                  //expression    : false,
-                  //global_defs   : {},
-                  //hoist_funs    : false,
-                  //hoist_props   : true,
-                  //hoist_vars    : false,
-                  //ie8           : false,
-                  //if_return     : true,
-                  //inline        : true,
-                  //join_vars     : true,
-                  //keep_classnames: false,
-                  //keep_fargs    : true,
-                  //keep_fnames   : false,
-                  //keep_infinity : false,
-                  //loops         : true,
-                  //negate_iife   : true,
-                  //passes        : 1,
-                  //properties    : true,
-                  //pure_getters  : true && "strict",
-                  //pure_funcs    : null,
-                  //reduce_funcs  : true,
-                  //reduce_vars   : true,
-                  //sequences     : true,
-                  //side_effects  : true,
-                  //switches      : true,
-                  //top_retain    : null,
-                  //toplevel      : !!(options && options["top_retain"]),
-                  //typeofs       : true,
-                  //unsafe        : false,
-                  //unsafe_arrows : false,
-                  //unsafe_comps  : false,
-                  //unsafe_Function: false,
-                  //unsafe_math   : false,
-                  //unsafe_methods: false,
-                  //unsafe_proto  : false,
-                  //unsafe_regexp : false,
-                  //unsafe_undefined: false,
-                  //unused        : true,
-                  //warnings      : false,
-                //},
-                //ecma: undefined,
-                //ie8: false,
-                //keep_classnames: undefined,
-                //keep_fnames: false,
-                //mangle: {},
-                //nameCache: null,
-                //output: {
-                  //ascii_only       : false,
-                  //beautify         : false,
-                  //bracketize       : false,
-                  //comments         : false,
-                  //ecma             : 5,
-                  //ie8              : false,
-                  //indent_level     : 4,
-                  //indent_start     : 0,
-                  //inline_script    : true,
-                  //keep_quoted_props: false,
-                  //max_line_len     : false,
-                  //preamble         : null,
-                  //preserve_line    : false,
-                  //quote_keys       : false,
-                  //quote_style      : 0,
-                  //safari10         : false,
-                  //semicolons       : true,
-                  //shebang          : true,
-                  //shorthand        : undefined,
-                  //source_map       : null,
-                  //webkit           : false,
-                  //width            : 80,
-                  //wrap_iife        : false
-                //},
-                //parse: {
-                  //bare_returns   : false,
-                  //ecma           : 8,
-                  //expression     : false,
-                  //filename       : null,
-                  //html5_comments : true,
-                  //shebang        : true,
-                  //strict         : false,
-                  //toplevel       : null
-                //},
-                //rename: undefined,
-                //safari10: false,
-                //sourceMap: false,
-                //timings: false,
-                toplevel: true //false,
-                //warnings: false,
-                //wrap: false
-              }
-            )
-            if (render.error !== undefined)
-              throw render.error
-            return /*await*/ fs_writeFile(
-              built_pathname,
-              render.code,
-              {encoding: 'utf-8'}
-            )
-          }
-        )
-      )
-    }
-  )
-}
-
-Server.prototype.get_svg_min = function(pathname) {
-  return /*await*/ this.build_cache_svg_min.get(
-    pathname,
-    async result => {
-      result.value = fs_readFile(
-        await disk_build(
-          pathname,
-          async built_pathname => {
-            console.log('getting', pathname, 'as svg_min')
-            let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-            console.log('building', built_pathname)
-            let render = await svgo.optimize(text, {path: pathname})
-            return /*await*/ fs_writeFile(
-              built_pathname,
-              render.data,
-              {encoding: 'utf-8'}
-            )
-          }
-        )
-      )
-    }
-  )
-}
-
-Server.prototype.get_text = function(pathname) {
-  return /*await*/ this.build_cache_text.get(
-    pathname,
-    async result => {
-      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
-      console.log('getting', pathname, 'as text')
-      result.value = text
-    }
-  )
-}
-
-Server.prototype.get_zet = function(pathname) {
-  return /*await*/ this.build_cache_zet.get(
-    pathname,
-    async result => {
-      console.log('getting', pathname, 'as zet')
-      result.deps = [
-        pathname + '.map.0',
-        pathname + '.param.0',
-        pathname + '.v.0',
-        pathname + '.vocab.0'
-      ]
-      result.value = new zetjs.Index(pathname)
-    }
-  )
-}
-
-Server.prototype.get_zip = function(pathname) {
-  return /*await*/ this.build_cache_zip.get(
-    pathname,
-    async result => {
-      let zipfile = await yauzl_open(pathname, {autoClose: false})
-      console.log('getting', pathname, 'as zip')
-
-      let entries = []
-      await new Promise(
-        (resolve, reject) => {
-          zipfile.
-          on('entry', entry => {entries.push(entry)}).
-          on('end', () => resolve())
-        }
-      )
-
-      result.value = {}
-      for (let i = 0; i < entries.length; ++i) {
-        let read_stream = await new Promise(
-          (resolve, reject) => {
-            zipfile.openReadStream(
-              entries[i],
-              (err, stream) => {
-                if (err)
-                  reject(err)
-                resolve(stream)
-              }
-            )
-          }
-        )
-
-        let write_stream = new stream_buffers.WritableStreamBuffer()
-        let data = new Promise(
-          (resolve, reject) => {
-            write_stream.
-            on('finish', () => {resolve(write_stream.getContents())}).
-            on('error', err => {reject(err)})
-          }
-        )
-        read_stream.pipe(write_stream)
-        data = await data
-
-        let entry_pathname = '/' + entries[i].fileName
-        console.log('entry pathname', entry_pathname, 'size', data.length)
-        result.value[entry_pathname] = data
-      }
-      await zipfile.close()
-    }
-  )
-}
-
-Server.prototype.ensure_dir = async function(pathname) {
-  try {
-    await fs_mkdir(pathname)
-    console.log('create directory', pathname)
-  }
-  catch (err) {
-    if (err.code !== 'EEXIST') // should check error type
-      throw err
-  }
-}
-
-// this is for read/write JSON files
-// they will not be reloaded from disk if modified
-Server.prototype.read_json = async function(pathname, default_value) {
-  return /*await*/ this.json_cache.read(
-    pathname,
-    default_value
-  )
-}
-Server.prototype.write_json = async function(pathname, value, timeout) {
-  return /*await*/ this.json_cache.write(
-    pathname,
-    value,
-    timeout
-  )
-}
-Server.prototype.modify_json =
-  async function(pathname, default_value, modify_func, timeout) {
-    return /*await*/ this.json_cache.modify(
-      pathname,
-      default_value,
-      modify_func,
-      timeout
-    )
-  }
-
 let compare_listen = (a, b) => {
   if (a.port < b.port)
     return -1
@@ -506,7 +55,7 @@ Server.prototype.attach = function(server, protocol) {
 
 Server.prototype.refresh_config = async function() {
   try {
-    let config = await this.get_jst('_config/server.jst', '.')
+    let config = await jst('_config/server.jst', '.', {_server: this})
 
     this.enable_caching = config.enable_caching
 
@@ -721,8 +270,7 @@ Server.prototype.respond = async function(request, response, protocol) {
         parsed_url: parsed_url,
         pathname: parsed_url.pathname,
         response: response,
-        request: request,
-        site: site
+        request: request
       }
     )
   }
index 0864575..c03b3f3 100644 (file)
+let BuildCache = require('@ndcode/build_cache')
+let CleanCSS = require('@ndcode/clean-css')
+let JSONCache = require('@ndcode/json_cache')
 let Site = require('./Site')
+let SVGO = require('svgo')
 let assert = require('assert')
+let disk_build = require('@ndcode/disk_build')
+let emailjs = require('emailjs')
 let fs = require('fs')
+let html_minifier = require('html-minifier')
+let jst = require('@ndcode/jst')
+let less = require('less/lib/less-node')
+let path = require('path')
+var stream_buffers = require('stream-buffers')
+let uglify_es = require('uglify-es')
 let util = require('util')
+let yauzl = require('yauzl')
+let zetjs = require('zetjs')
 
+let fs_mkdir = util.promisify(fs.mkdir)
 let fs_readFile = util.promisify(fs.readFile)
 let fs_stat = util.promisify(fs.stat)
+let fs_writeFile = util.promisify(fs.writeFile)
+let yauzl_open = util.promisify(yauzl.open)
+let clean_css = new CleanCSS({returnPromise: true})
+let svgo = new SVGO(
+  {
+    plugins: [
+      {cleanupAttrs: true},
+      {removeDoctype: true},
+      {removeXMLProcInst: true},
+      {removeComments: true},
+      {removeMetadata: true},
+      {removeTitle: true},
+      {removeDesc: true},
+      {removeUselessDefs: true},
+      {removeEditorsNSData: true},
+      {removeEmptyAttrs: true},
+      {removeHiddenElems: true},
+      {removeEmptyText: true},
+      {removeEmptyContainers: true},
+      {removeViewBox: false},
+      {cleanupEnableBackground: true},
+      {convertStyleToAttrs: true},
+      {convertColors: true},
+      {convertPathData: true},
+      {convertTransform: true},
+      {removeUnknownsAndDefaults: true},
+      {removeNonInheritableGroupAttrs: true},
+      {removeUselessStrokeAndFill: true},
+      {removeUnusedNS: true},
+      {cleanupIDs: true},
+      {cleanupNumericValues: true},
+      {moveElemsAttrsToGroup: true},
+      {moveGroupAttrsToElems: true},
+      {collapseGroups: true},
+      {removeRasterImages: false},
+      {mergePaths: true},
+      {convertShapeToPath: true},
+      {sortAttrs: true},
+      {removeDimensions: true}//,
+      //{removeAttrs: {attrs: '(stroke|fill)'}}
+    ]
+  }
+)
 
 let SiteRoot = function(server, root) {
   if (!this instanceof SiteRoot)
     throw Error('SiteRoot is a constructor')
   Site.call(this, server)
   this.root = root
+
+  this.build_cache_email = new BuildCache()
+  this.build_cache_json = new BuildCache()
+  this.build_cache_css_less = new BuildCache()
+  this.build_cache_css_min = new BuildCache()
+  this.build_cache_html_min = new BuildCache()
+  this.build_cache_js_min = new BuildCache()
+  this.build_cache_svg_min = new BuildCache()
+  this.build_cache_text = new BuildCache()
+  this.build_cache_zet = new BuildCache()
+  this.build_cache_zip = new BuildCache()
+  this.json_cache = new JSONCache(true)
 }
 
 SiteRoot.prototype = Object.create(Site.prototype)
 
+SiteRoot.prototype.internal_get_email = function(pathname) {
+  return /*await*/ this.build_cache_email.get(
+    pathname,
+    async result => {
+      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+      console.log('getting', pathname, 'as email')
+      result.value = emailjs.server.connect(JSON.parse(text))
+    }
+  )
+}
+
+// this is for read-only JSON files
+// they will be reloaded from disk if modified
+SiteRoot.prototype.internal_get_json = function(pathname) {
+  return /*await*/ this.build_cache_json.get(
+    pathname,
+    async result => {
+      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+      console.log('getting', pathname, 'as json')
+      result.value = JSON.parse(text)
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_jst = function(pathname, root) {
+  return /*await*/ jst(pathname, root, {_server: this.server, _site: this})
+}
+
+SiteRoot.prototype.internal_get_css_less = function(pathname, root) {
+  let dirname = path.posix.dirname(pathname)
+  return /*await*/ this.build_cache_css_less.get(
+    pathname,
+    async result => {
+      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+      console.log('getting', pathname, 'as css_less')
+      let render = await less.render(
+        text,
+        {
+          //color: true,
+          //compress: false,
+          //depends: false,
+          filename: pathname,
+          //globalVars: null,
+          //ieCompat: false,
+          //insecure: false,
+          //javascriptEnabled: false,
+          //lint: false,
+          //math: 0,
+          //modifyVars: null,
+          pathnames: [dirname],
+          //plugins: [],
+          //reUsePluginManager: true,
+          //rewriteUrls: false,
+          rootpathname: root//,
+          //strictImports: false,
+          //strictUnits: false,
+          //urlArgs: ''
+        }
+      )
+      result.deps.concat(render.imports)
+      result.value = Buffer.from(render.css)
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_css_min = function(pathname) {
+  return /*await*/ this.build_cache_css_min.get(
+    pathname,
+    async result => {
+      result.value = fs_readFile(
+        await disk_build(
+          pathname,
+          async built_pathname => {
+            console.log('getting', pathname, 'as css_min')
+            let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+            console.log('building', built_pathname)
+            let render = await clean_css.minify(text)
+            for (let i = 0; i < render.warnings.length; ++i)
+              console.log(`clean-css warning: ${render.warnings[i]}`)
+            return /*await*/ fs_writeFile(
+              built_pathname,
+              render.styles,
+              {encoding: 'utf-8'}
+            )
+          }
+        )
+      )
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_html_min = function(pathname) {
+  return /*await*/ this.build_cache_html_min.get(
+    pathname,
+    async result => {
+      result.value = fs_readFile(
+        await disk_build(
+          pathname,
+          async built_pathname => {
+            console.log('getting', pathname, 'as html_min')
+            let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+            console.log('building', built_pathname)
+            return /*await*/ fs_writeFile(
+              built_pathname,
+              html_minifier.minify(text, {collapseWhitespace: true}),
+              {encoding: 'utf-8'}
+            )
+          }
+        )
+      )
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_js_min = function(pathname) {
+  return /*await*/ this.build_cache_js_min.get(
+    pathname,
+    async result => {
+      result.value = fs_readFile(
+        await disk_build(
+          pathname,
+          async built_pathname => {
+            console.log('getting', pathname, 'as js_min')
+            let files = {}
+            files[pathname] = await fs_readFile(pathname, {encoding: 'utf-8'})
+            console.log('building', built_pathname)
+            let render = uglify_es.minify(
+              files,
+              {
+                //compress: {
+                  //arrows        : true,
+                  //booleans      : true,
+                  //collapse_vars : true,
+                  //comparisons   : true,
+                  //computed_props: true,
+                  //conditionals  : true,
+                  //dead_code     : true,
+                  //drop_console  : false,
+                  //drop_debugger : true,
+                  //ecma          : 5,
+                  //evaluate      : true,
+                  //expression    : false,
+                  //global_defs   : {},
+                  //hoist_funs    : false,
+                  //hoist_props   : true,
+                  //hoist_vars    : false,
+                  //ie8           : false,
+                  //if_return     : true,
+                  //inline        : true,
+                  //join_vars     : true,
+                  //keep_classnames: false,
+                  //keep_fargs    : true,
+                  //keep_fnames   : false,
+                  //keep_infinity : false,
+                  //loops         : true,
+                  //negate_iife   : true,
+                  //passes        : 1,
+                  //properties    : true,
+                  //pure_getters  : true && "strict",
+                  //pure_funcs    : null,
+                  //reduce_funcs  : true,
+                  //reduce_vars   : true,
+                  //sequences     : true,
+                  //side_effects  : true,
+                  //switches      : true,
+                  //top_retain    : null,
+                  //toplevel      : !!(options && options["top_retain"]),
+                  //typeofs       : true,
+                  //unsafe        : false,
+                  //unsafe_arrows : false,
+                  //unsafe_comps  : false,
+                  //unsafe_Function: false,
+                  //unsafe_math   : false,
+                  //unsafe_methods: false,
+                  //unsafe_proto  : false,
+                  //unsafe_regexp : false,
+                  //unsafe_undefined: false,
+                  //unused        : true,
+                  //warnings      : false,
+                //},
+                //ecma: undefined,
+                //ie8: false,
+                //keep_classnames: undefined,
+                //keep_fnames: false,
+                //mangle: {},
+                //nameCache: null,
+                //output: {
+                  //ascii_only       : false,
+                  //beautify         : false,
+                  //bracketize       : false,
+                  //comments         : false,
+                  //ecma             : 5,
+                  //ie8              : false,
+                  //indent_level     : 4,
+                  //indent_start     : 0,
+                  //inline_script    : true,
+                  //keep_quoted_props: false,
+                  //max_line_len     : false,
+                  //preamble         : null,
+                  //preserve_line    : false,
+                  //quote_keys       : false,
+                  //quote_style      : 0,
+                  //safari10         : false,
+                  //semicolons       : true,
+                  //shebang          : true,
+                  //shorthand        : undefined,
+                  //source_map       : null,
+                  //webkit           : false,
+                  //width            : 80,
+                  //wrap_iife        : false
+                //},
+                //parse: {
+                  //bare_returns   : false,
+                  //ecma           : 8,
+                  //expression     : false,
+                  //filename       : null,
+                  //html5_comments : true,
+                  //shebang        : true,
+                  //strict         : false,
+                  //toplevel       : null
+                //},
+                //rename: undefined,
+                //safari10: false,
+                //sourceMap: false,
+                //timings: false,
+                toplevel: true //false,
+                //warnings: false,
+                //wrap: false
+              }
+            )
+            if (render.error !== undefined)
+              throw render.error
+            return /*await*/ fs_writeFile(
+              built_pathname,
+              render.code,
+              {encoding: 'utf-8'}
+            )
+          }
+        )
+      )
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_svg_min = function(pathname) {
+  return /*await*/ this.build_cache_svg_min.get(
+    pathname,
+    async result => {
+      result.value = fs_readFile(
+        await disk_build(
+          pathname,
+          async built_pathname => {
+            console.log('getting', pathname, 'as svg_min')
+            let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+            console.log('building', built_pathname)
+            let render = await svgo.optimize(text, {path: pathname})
+            return /*await*/ fs_writeFile(
+              built_pathname,
+              render.data,
+              {encoding: 'utf-8'}
+            )
+          }
+        )
+      )
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_text = function(pathname) {
+  return /*await*/ this.build_cache_text.get(
+    pathname,
+    async result => {
+      let text = await fs_readFile(pathname, {encoding: 'utf-8'})
+      console.log('getting', pathname, 'as text')
+      result.value = text
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_zet = function(pathname) {
+  return /*await*/ this.build_cache_zet.get(
+    pathname,
+    async result => {
+      console.log('getting', pathname, 'as zet')
+      result.deps = [
+        pathname + '.map.0',
+        pathname + '.param.0',
+        pathname + '.v.0',
+        pathname + '.vocab.0'
+      ]
+      result.value = new zetjs.Index(pathname)
+    }
+  )
+}
+
+SiteRoot.prototype.internal_get_zip = function(pathname) {
+  return /*await*/ this.build_cache_zip.get(
+    pathname,
+    async result => {
+      let zipfile = await yauzl_open(pathname, {autoClose: false})
+      console.log('getting', pathname, 'as zip')
+
+      let entries = []
+      await new Promise(
+        (resolve, reject) => {
+          zipfile.
+          on('entry', entry => {entries.push(entry)}).
+          on('end', () => resolve())
+        }
+      )
+
+      result.value = {}
+      for (let i = 0; i < entries.length; ++i) {
+        let read_stream = await new Promise(
+          (resolve, reject) => {
+            zipfile.openReadStream(
+              entries[i],
+              (err, stream) => {
+                if (err)
+                  reject(err)
+                resolve(stream)
+              }
+            )
+          }
+        )
+
+        let write_stream = new stream_buffers.WritableStreamBuffer()
+        let data = new Promise(
+          (resolve, reject) => {
+            write_stream.
+            on('finish', () => {resolve(write_stream.getContents())}).
+            on('error', err => {reject(err)})
+          }
+        )
+        read_stream.pipe(write_stream)
+        data = await data
+
+        let entry_pathname = '/' + entries[i].fileName
+        console.log('entry pathname', entry_pathname, 'size', data.length)
+        result.value[entry_pathname] = data
+      }
+      await zipfile.close()
+    }
+  )
+}
+
+SiteRoot.prototype.internal_ensure_dir = async function(pathname) {
+  try {
+    await fs_mkdir(pathname)
+    console.log('create directory', pathname)
+  }
+  catch (err) {
+    if (err.code !== 'EEXIST') // should check error type
+      throw err
+  }
+}
+
+// this is for read/write JSON files
+// they will not be reloaded from disk if modified
+SiteRoot.prototype.internal_read_json =
+  async function(pathname, default_value) {
+    return /*await*/ this.json_cache.read(
+      pathname,
+      default_value
+    )
+  }
+SiteRoot.prototype.internal_write_json =
+  async function(pathname, value, timeout) {
+    return /*await*/ this.json_cache.write(
+      pathname,
+      value,
+      timeout
+    )
+  }
+SiteRoot.prototype.internal_modify_json =
+  async function(pathname, default_value, modify_func, timeout) {
+    return /*await*/ this.json_cache.modify(
+      pathname,
+      default_value,
+      modify_func,
+      timeout
+    )
+  }
+
 SiteRoot.prototype.get_email = function(pathname) {
-  return /*await*/ this.server.get_email(this.root + pathname)
+  return /*await*/ this.internal_get_email(this.root + pathname)
 }
 SiteRoot.prototype.get_json = function(pathname) {
-  return /*await*/ this.server.get_json(this.root + pathname)
+  return /*await*/ this.internal_get_json(this.root + pathname)
 }
 SiteRoot.prototype.get_jst = function(pathname) {
-  return /*await*/ this.server.get_jst(this.root + pathname, this.root)
+  return /*await*/ this.internal_get_jst(this.root + pathname, this.root)
 }
 SiteRoot.prototype.get_css_less = function(pathname) {
-  return /*await*/ this.server.get_css_less(this.root + pathname, this.root)
+  return /*await*/ this.internal_get_css_less(this.root + pathname, this.root)
 }
 SiteRoot.prototype.get_css_min = function(pathname) {
-  return /*await*/ this.server.get_css_min(this.root + pathname)
+  return /*await*/ this.internal_get_css_min(this.root + pathname)
 }
 SiteRoot.prototype.get_html_min = function(pathname) {
-  return /*await*/ this.server.get_html_min(this.root + pathname)
+  return /*await*/ this.internal_get_html_min(this.root + pathname)
 }
 SiteRoot.prototype.get_js_min = function(pathname) {
-  return /*await*/ this.server.get_js_min(this.root + pathname)
+  return /*await*/ this.internal_get_js_min(this.root + pathname)
 }
 SiteRoot.prototype.get_svg_min = function(pathname) {
-  return /*await*/ this.server.get_svg_min(this.root + pathname)
+  return /*await*/ this.internal_get_svg_min(this.root + pathname)
 }
 SiteRoot.prototype.get_text = function(pathname) {
-  return /*await*/ this.server.get_text(this.root + pathname)
+  return /*await*/ this.internal_get_text(this.root + pathname)
 }
 SiteRoot.prototype.get_zet = function(pathname) {
-  return /*await*/ this.server.get_zet(this.root + pathname)
+  return /*await*/ this.internal_get_zet(this.root + pathname)
 }
 SiteRoot.prototype.get_zip = function(pathname) {
-  return /*await*/ this.server.get_zip(this.root + pathname)
+  return /*await*/ this.internal_get_zip(this.root + pathname)
 }
 
 SiteRoot.prototype.ensure_dir = async function(pathname) {
-  return /*await*/ this.server.ensure_dir(this.root + pathname)
+  return /*await*/ this.internal_ensure_dir(this.root + pathname)
 }
 
 // this is for read/write JSON files
 // they will not be reloaded from disk if modified
 SiteRoot.prototype.read_json = async function(pathname, default_value) {
-  return /*await*/ this.server.read_json(
+  return /*await*/ this.internal_read_json(
     this.root + pathname,
     default_value
   )
 }
 SiteRoot.prototype.write_json = async function(pathname, value, timeout) {
-  return /*await*/ this.server.write_json(
+  return /*await*/ this.internal_write_json(
     this.root + pathname,
     value,
     timeout
@@ -70,7 +524,7 @@ SiteRoot.prototype.write_json = async function(pathname, value, timeout) {
 }
 SiteRoot.prototype.modify_json =
   async function(pathname, default_value, modify_func, timeout) {
-    return /*await*/ this.server.modify_json(
+    return /*await*/ this.internal_modify_json(
       this.root + pathname,
       default_value,
       modify_func,
@@ -81,7 +535,7 @@ SiteRoot.prototype.modify_json =
 SiteRoot.prototype.serve_jst = async function(env, pathname, ...args) {
   let template
   try {
-    template = await this.server.get_jst(pathname, this.root)
+    template = await this.internal_get_jst(pathname, this.root)
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
@@ -98,7 +552,7 @@ SiteRoot.prototype.serve_css_less = async function(env, pathname) {
  
   let data 
   try {
-    data = await this.server.get_css_less(pathname, this.root)
+    data = await this.internal_get_css_less(pathname, this.root)
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
@@ -115,7 +569,7 @@ SiteRoot.prototype.serve_css_min = async function(env, pathname) {
  
   let data 
   try {
-    data = await this.server.get_css_min(pathname)
+    data = await this.internal_get_css_min(pathname)
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
@@ -132,7 +586,7 @@ SiteRoot.prototype.serve_js_min = async function(env, pathname) {
  
   let data 
   try {
-    data = await this.server.get_js_min(pathname)
+    data = await this.internal_get_js_min(pathname)
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
@@ -160,7 +614,7 @@ SiteRoot.prototype.serve_fs = async function(env, pathname) {
 SiteRoot.prototype.serve_zip = async function(env, zipname, pathname) {
   let zip 
   try {
-    zip = await this.server.get_zip(zipname)
+    zip = await this.internal_get_zip(zipname)
   }
   catch (err) {
     if (!(err instanceof Error) || err.code !== 'ENOENT')
index a9bcebd..c217763 100644 (file)
@@ -1,5 +1,5 @@
 return async env => {
-  env.site.serve(
+  _site.serve(
     env,
     200,
     Buffer.from(