From 39b1fa89ce9c179c3cb8beeea59c0d90deab56a5 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 11:03:23 -0500 Subject: [PATCH 1/9] wip --- cli.js | 932 ++++++++++++++++++ lib/config.js | 21 - middleware.js | 772 +++++++++++++++ mocha.opts | 1 + package-lock.json | 535 +++++----- package.json | 13 +- rollup.config.js | 69 ++ runtime/README.md | 1 + {cli => src/cli}/index.js | 7 +- src/config.js | 21 + {lib => src/middleware}/index.js | 24 +- src/middleware/tmp.json | 154 +++ {lib => src/shared}/build.js | 18 +- {lib/utils => src/shared}/export.js | 26 +- .../shared}/generate_asset_cache.js | 16 +- src/shared/index.js | 7 + {lib => src/shared}/route_manager.js | 14 +- {lib => src/shared}/templates.js | 20 +- {lib => src/shared}/utils/compilers.js | 9 +- {lib => src/shared}/utils/create_app.js | 10 +- {lib => src/shared}/utils/create_routes.js | 6 +- {lib => src/shared}/utils/create_watcher.js | 16 +- src/webpack/index.js | 44 + test/common/test.js | 21 +- test/unit/create_routes.test.js | 5 +- webpack/config.js | 30 +- webpack/hmr.js | 1 - 27 files changed, 2392 insertions(+), 401 deletions(-) create mode 100644 cli.js delete mode 100644 lib/config.js create mode 100644 middleware.js create mode 100644 runtime/README.md rename {cli => src/cli}/index.js (85%) create mode 100644 src/config.js rename {lib => src/middleware}/index.js (91%) create mode 100644 src/middleware/tmp.json rename {lib => src/shared}/build.js (72%) rename {lib/utils => src/shared}/export.js (82%) rename {lib/utils => src/shared}/generate_asset_cache.js (85%) create mode 100644 src/shared/index.js rename {lib => src/shared}/route_manager.js (66%) rename {lib => src/shared}/templates.js (91%) rename {lib => src/shared}/utils/compilers.js (54%) rename {lib => src/shared}/utils/create_app.js (92%) rename {lib => src/shared}/utils/create_routes.js (95%) rename {lib => src/shared}/utils/create_watcher.js (83%) create mode 100644 src/webpack/index.js delete mode 100644 webpack/hmr.js diff --git a/cli.js b/cli.js new file mode 100644 index 0000000..d5af45d --- /dev/null +++ b/cli.js @@ -0,0 +1,932 @@ +#!/usr/bin/env node +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var fs = require('fs'); +var path = require('path'); +var mkdirp = _interopDefault(require('mkdirp')); +var rimraf = _interopDefault(require('rimraf')); +var relative = _interopDefault(require('require-relative')); +var glob = _interopDefault(require('glob')); +var chalk = _interopDefault(require('chalk')); +var framer = _interopDefault(require('code-frame')); +var locateCharacter = require('locate-character'); +var sander = require('sander'); +var express = _interopDefault(require('express')); +var cheerio = _interopDefault(require('cheerio')); +var fetch = _interopDefault(require('node-fetch')); +var URL = _interopDefault(require('url-parse')); +var serialize = _interopDefault(require('serialize-javascript')); +var escape_html = _interopDefault(require('escape-html')); + +const webpack = relative('webpack', process.cwd()); + +const client = webpack( + require(path.resolve('webpack.client.config.js')) +); + +const server = webpack( + require(path.resolve('webpack.server.config.js')) +); + +var compilers = Object.freeze({ + client: client, + server: server +}); + +function create_matchers(files) { + const routes = files + .map(file => { + if (/(^|\/|\\)_/.test(file)) return; + + const parts = file.replace(/\.(html|js|mjs)$/, '').split('/'); // glob output is always posix-style + if (parts[parts.length - 1] === 'index') parts.pop(); + + const id = ( + parts.join('_').replace(/[[\]]/g, '$').replace(/^\d/, '_$&').replace(/[^a-zA-Z0-9_$]/g, '_') + ) || '_'; + + const dynamic = parts + .filter(part => part[0] === '[') + .map(part => part.slice(1, -1)); + + let pattern_string = ''; + let i = parts.length; + let nested = true; + while (i--) { + const part = parts[i]; + const dynamic = part[0] === '['; + + if (dynamic) { + pattern_string = nested ? `(?:\\/([^/]+)${pattern_string})?` : `\\/([^/]+)${pattern_string}`; + } else { + nested = false; + pattern_string = `\\/${part}${pattern_string}`; + } + } + + const pattern = new RegExp(`^${pattern_string}\\/?$`); + + const test = url => pattern.test(url); + + const exec = url => { + const match = pattern.exec(url); + if (!match) return; + + const params = {}; + dynamic.forEach((param, i) => { + params[param] = match[i + 1]; + }); + + return params; + }; + + return { + id, + type: path.extname(file) === '.html' ? 'page' : 'route', + file, + pattern, + test, + exec, + parts, + dynamic + }; + }) + .filter(Boolean) + .sort((a, b) => { + let same = true; + + for (let i = 0; true; i += 1) { + const a_part = a.parts[i]; + const b_part = b.parts[i]; + + if (!a_part && !b_part) { + if (same) throw new Error(`The ${a.file} and ${b.file} routes clash`); + return 0; + } + + if (!a_part) return -1; + if (!b_part) return 1; + + const a_is_dynamic = a_part[0] === '['; + const b_is_dynamic = b_part[0] === '['; + + if (a_is_dynamic === b_is_dynamic) { + if (!a_is_dynamic && a_part !== b_part) same = false; + continue; + } + + return a_is_dynamic ? 1 : -1; + } + }); + + return routes; +} + +const dev = process.env.NODE_ENV !== 'production'; + +const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); + +const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); + +const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); + +if (dev) { + mkdirp.sync(dest); + rimraf.sync(path.join(dest, '**/*')); +} + +const entry = { + client: path.resolve(templates, '.main.rendered.js'), + server: path.resolve(dest, 'server-entry.js') +}; + +const callbacks = []; + +function onchange(fn) { + callbacks.push(fn); +} + +let routes; + +function update() { + routes = create_matchers( + glob.sync('**/*.+(html|js|mjs)', { cwd: src }) + ); + + callbacks.forEach(fn => fn()); +} + +update(); + +if (dev) { + const watcher = require('chokidar').watch(`${src}/**/*.+(html|js|mjs)`, { + ignoreInitial: true, + persistent: false + }); + + watcher.on('add', update); + watcher.on('change', update); + watcher.on('unlink', update); +} + + +var route_manager = Object.freeze({ + onchange: onchange, + get routes () { return routes; } +}); + +function posixify(file) { + return file.replace(/[/\\]/g, '/'); +} + +function create_app() { + const { routes: routes$$1 } = route_manager; + + function create_client_main() { + const template = fs.readFileSync('templates/main.js', 'utf-8'); + + const code = `[${ + routes$$1 + .filter(route => route.type === 'page') + .map(route => { + const params = route.dynamic.length === 0 ? + '{}' : + `{ ${route.dynamic.map((part, i) => `${part}: match[${i + 1}]`).join(', ') } }`; + + const file = posixify(`${src}/${route.file}`); + return `{ pattern: ${route.pattern}, params: match => (${params}), load: () => import(/* webpackChunkName: "${route.id}" */ '${file}') }` + }) + .join(', ') + }]`; + + let main = template + .replace(/__app__/g, posixify(path.resolve(__dirname, '../../runtime/app.js'))) + .replace(/__routes__/g, code) + .replace(/__dev__/g, String(dev)); + + if (dev) { + const hmr_client = posixify(require.resolve(`webpack-hot-middleware/client`)); + main += `\n\nimport('${hmr_client}?path=/__webpack_hmr&timeout=20000'); if (module.hot) module.hot.accept();`; + } + + fs.writeFileSync(entry.client, main); + + // need to fudge the mtime, because webpack is soft in the head + const { atime, mtime } = fs.statSync(entry.client); + fs.utimesSync(entry.client, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); + } + + function create_server_routes() { + const imports = routes$$1 + .map(route => { + const file = posixify(`${src}/${route.file}`); + return route.type === 'page' ? + `import ${route.id} from '${file}';` : + `import * as ${route.id} from '${file}';`; + }) + .join('\n'); + + const exports = `export { ${routes$$1.map(route => route.id)} };`; + + fs.writeFileSync(entry.server, `${imports}\n\n${exports}`); + + const { atime, mtime } = fs.statSync(entry.server); + fs.utimesSync(entry.server, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); + } + + create_client_main(); + create_server_routes(); +} + +if (dev) { + onchange(create_app); + + const watcher = require('chokidar').watch(`templates/main.js`, { + ignoreInitial: true, + persistent: false + }); + + watcher.on('add', create_app); + watcher.on('change', create_app); + watcher.on('unlink', create_app); +} + +let templates$1; + +function error(e) { + if (e.title) console.error(chalk.bold.red(e.title)); + if (e.body) console.error(chalk.red(e.body)); + if (e.url) console.error(chalk.cyan(e.url)); + if (e.frame) console.error(chalk.grey(e.frame)); + + process.exit(1); +} + +function create_templates() { + templates$1 = glob.sync('*.html', { cwd: 'templates' }) + .map(file => { + const template = fs.readFileSync(`templates/${file}`, 'utf-8'); + const status = file.replace('.html', '').toLowerCase(); + + if (!/^[0-9x]{3}$/.test(status)) { + error({ + title: `templates/${file}`, + body: `Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html` + }); + } + + const index = template.indexOf('%sapper.main%'); + if (index !== -1) { + // TODO remove this in a future version + const { line, column } = locateCharacter.locate(template, index, { offsetLine: 1 }); + const frame = framer(template, line, column); + + error({ + title: `templates/${file}`, + body: ``; + + if (serialized) { + return `${main}`; + } + + return main; + }), + html: promise.then(({ rendered }) => rendered.html), + head: promise.then(({ rendered }) => `${rendered.head}`), + styles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `` : '')) + }); + } else { + const { html, head, css } = mod.render(data); + + const page = render(200, { + scripts: ``, + html, + head: `${head}`, + styles: (css && css.code ? `` : '') + }); + + res.end(page); + } + } + + else { + const method = req.method.toLowerCase(); + // 'delete' cannot be exported from a module because it is a keyword, + // so check for 'del' instead + const method_export = method === 'delete' ? 'del' : method; + const handler = mod[method_export]; + if (handler) { + handler(req, res, next); + } else { + // no matching handler for method — 404 + next(); + } + } + } + + return function find_route(req, res, next) { + const url = req.pathname; + + // whatever happens, we're going to serve some HTML + res.setHeader('Content-Type', 'text/html'); + + resolved + .then(() => { + for (const route of routes) { + if (route.test(url)) return handle_route(route, req, res, next, fn()); + } + + // no matching route — 404 + next(); + }) + .catch(err => { + res.statusCode = 500; + res.end(render(500, { + title: (err && err.name) || 'Internal server error', + url, + error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), + stack: err && err.stack.split('\n').slice(1).join('\n') + })); + }); + }; +} + +function get_not_found_handler(fn) { + return function handle_not_found(req, res) { + const asset_cache = fn(); + + res.statusCode = 404; + res.end(render(404, { + title: 'Not found', + status: 404, + method: req.method, + scripts: ``, + url: req.url + })); + }; +} + +function compose_handlers(handlers) { + return (req, res, next) => { + let i = 0; + function go() { + const handler = handlers[i]; + + if (handler) { + handler(req, res, () => { + i += 1; + go(); + }); + } else { + next(); + } + } + + go(); + }; +} + +function read_json$1(file) { + return JSON.parse(fs.readFileSync(file, 'utf-8')); +} + +function try_serialize(data) { + try { + return serialize(data); + } catch (err) { + return null; + } +} + +const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env; + +const origin = `http://localhost:${PORT}`; + +const app = express(); + +function read_json(file) { + return JSON.parse(sander.readFileSync(file, { encoding: 'utf-8' })); +} + +function exporter() { + // Prep output directory + sander.rimrafSync(OUTPUT_DIR); + + const { service_worker } = generate_asset_cache( + read_json(path.join(dest, 'stats.client.json')), + read_json(path.join(dest, 'stats.server.json')) + ); + + sander.copydirSync('assets').to(OUTPUT_DIR); + sander.copydirSync(dest, 'client').to(OUTPUT_DIR, 'client'); + sander.writeFileSync(OUTPUT_DIR, 'service-worker.js', service_worker); + + // Intercept server route fetches + function save(res) { + res = res.clone(); + + return res.text().then(body => { + const { pathname } = new URL(res.url); + let dest$$1 = OUTPUT_DIR + pathname; + + const type = res.headers.get('Content-Type'); + if (type.startsWith('text/html')) dest$$1 += '/index.html'; + + sander.writeFileSync(dest$$1, body); + + return body; + }); + } + + global.fetch = (url, opts) => { + if (url[0] === '/') { + url = `http://localhost:${PORT}${url}`; + + return fetch(url, opts) + .then(r => { + save(r); + return r; + }); + } + + return fetch(url, opts); + }; + + app.use(middleware()); + const server = app.listen(PORT); + + const seen = new Set(); + + function handle(url) { + if (url.origin !== origin) return; + + if (seen.has(url.pathname)) return; + seen.add(url.pathname); + + return fetch(url.href) + .then(r => { + save(r); + return r.text(); + }) + .then(body => { + const $ = cheerio.load(body); + const hrefs = []; + + $('a[href]').each((i, $a) => { + hrefs.push($a.attribs.href); + }); + + return hrefs.reduce((promise, href) => { + return promise.then(() => handle(new URL(href, url.href))); + }, Promise.resolve()); + }) + .catch(err => { + console.error(`Error rendering ${url.pathname}: ${err.message}`); + }); + } + + return handle(new URL(origin)) // TODO all static routes + .then(() => server.close()); +} + +const cmd = process.argv[2]; +const start = Date.now(); + +if (cmd === 'build') { + build() + .then(() => { + const elapsed = Date.now() - start; + console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' + }) + .catch(err => { + console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); + }); +} else if (cmd === 'export') { + const start = Date.now(); + + build() + .then(() => exporter()) + .then(() => { + const elapsed = Date.now() - start; + console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' + }) + .catch(err => { + console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); + }); +} diff --git a/lib/config.js b/lib/config.js deleted file mode 100644 index 27efcdc..0000000 --- a/lib/config.js +++ /dev/null @@ -1,21 +0,0 @@ -const path = require('path'); -const mkdirp = require('mkdirp'); -const rimraf = require('rimraf'); - -exports.dev = process.env.NODE_ENV !== 'production'; - -exports.templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); - -exports.src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); - -exports.dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); - -if (exports.dev) { - mkdirp.sync(exports.dest); - rimraf.sync(path.join(exports.dest, '**/*')); -} - -exports.entry = { - client: path.resolve(exports.templates, '.main.rendered.js'), - server: path.resolve(exports.dest, 'server-entry.js') -}; \ No newline at end of file diff --git a/middleware.js b/middleware.js new file mode 100644 index 0000000..c23539e --- /dev/null +++ b/middleware.js @@ -0,0 +1,772 @@ +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var fs = require('fs'); +var path = require('path'); +var serialize = _interopDefault(require('serialize-javascript')); +var escape_html = _interopDefault(require('escape-html')); +var glob = _interopDefault(require('glob')); +var mkdirp = _interopDefault(require('mkdirp')); +var rimraf = _interopDefault(require('rimraf')); +var chalk = _interopDefault(require('chalk')); +var framer = _interopDefault(require('code-frame')); +var locateCharacter = require('locate-character'); +var relative = _interopDefault(require('require-relative')); + +function create_matchers(files) { + const routes = files + .map(file => { + if (/(^|\/|\\)_/.test(file)) return; + + const parts = file.replace(/\.(html|js|mjs)$/, '').split('/'); // glob output is always posix-style + if (parts[parts.length - 1] === 'index') parts.pop(); + + const id = ( + parts.join('_').replace(/[[\]]/g, '$').replace(/^\d/, '_$&').replace(/[^a-zA-Z0-9_$]/g, '_') + ) || '_'; + + const dynamic = parts + .filter(part => part[0] === '[') + .map(part => part.slice(1, -1)); + + let pattern_string = ''; + let i = parts.length; + let nested = true; + while (i--) { + const part = parts[i]; + const dynamic = part[0] === '['; + + if (dynamic) { + pattern_string = nested ? `(?:\\/([^/]+)${pattern_string})?` : `\\/([^/]+)${pattern_string}`; + } else { + nested = false; + pattern_string = `\\/${part}${pattern_string}`; + } + } + + const pattern = new RegExp(`^${pattern_string}\\/?$`); + + const test = url => pattern.test(url); + + const exec = url => { + const match = pattern.exec(url); + if (!match) return; + + const params = {}; + dynamic.forEach((param, i) => { + params[param] = match[i + 1]; + }); + + return params; + }; + + return { + id, + type: path.extname(file) === '.html' ? 'page' : 'route', + file, + pattern, + test, + exec, + parts, + dynamic + }; + }) + .filter(Boolean) + .sort((a, b) => { + let same = true; + + for (let i = 0; true; i += 1) { + const a_part = a.parts[i]; + const b_part = b.parts[i]; + + if (!a_part && !b_part) { + if (same) throw new Error(`The ${a.file} and ${b.file} routes clash`); + return 0; + } + + if (!a_part) return -1; + if (!b_part) return 1; + + const a_is_dynamic = a_part[0] === '['; + const b_is_dynamic = b_part[0] === '['; + + if (a_is_dynamic === b_is_dynamic) { + if (!a_is_dynamic && a_part !== b_part) same = false; + continue; + } + + return a_is_dynamic ? 1 : -1; + } + }); + + return routes; +} + +const dev = process.env.NODE_ENV !== 'production'; + +const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); + +const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); + +const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); + +if (dev) { + mkdirp.sync(dest); + rimraf.sync(path.join(dest, '**/*')); +} + +const entry = { + client: path.resolve(templates, '.main.rendered.js'), + server: path.resolve(dest, 'server-entry.js') +}; + +const callbacks = []; + +function onchange(fn) { + callbacks.push(fn); +} + +let routes; + +function update() { + routes = create_matchers( + glob.sync('**/*.+(html|js|mjs)', { cwd: src }) + ); + + callbacks.forEach(fn => fn()); +} + +update(); + +if (dev) { + const watcher = require('chokidar').watch(`${src}/**/*.+(html|js|mjs)`, { + ignoreInitial: true, + persistent: false + }); + + watcher.on('add', update); + watcher.on('change', update); + watcher.on('unlink', update); +} + + +var route_manager = Object.freeze({ + onchange: onchange, + get routes () { return routes; } +}); + +let templates$1; + +function error(e) { + if (e.title) console.error(chalk.bold.red(e.title)); + if (e.body) console.error(chalk.red(e.body)); + if (e.url) console.error(chalk.cyan(e.url)); + if (e.frame) console.error(chalk.grey(e.frame)); + + process.exit(1); +} + +function create_templates() { + templates$1 = glob.sync('*.html', { cwd: 'templates' }) + .map(file => { + const template = fs.readFileSync(`templates/${file}`, 'utf-8'); + const status = file.replace('.html', '').toLowerCase(); + + if (!/^[0-9x]{3}$/.test(status)) { + error({ + title: `templates/${file}`, + body: `Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html` + }); + } + + const index = template.indexOf('%sapper.main%'); + if (index !== -1) { + // TODO remove this in a future version + const { line, column } = locateCharacter.locate(template, index, { offsetLine: 1 }); + const frame = framer(template, line, column); + + error({ + title: `templates/${file}`, + body: ``; + + if (serialized) { + return `${main}`; + } + + return main; + }), + html: promise.then(({ rendered }) => rendered.html), + head: promise.then(({ rendered }) => `${rendered.head}`), + styles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `` : '')) + }); + } else { + const { html, head, css } = mod.render(data); + + const page = render(200, { + scripts: ``, + html, + head: `${head}`, + styles: (css && css.code ? `` : '') + }); + + res.end(page); + } + } + + else { + const method = req.method.toLowerCase(); + // 'delete' cannot be exported from a module because it is a keyword, + // so check for 'del' instead + const method_export = method === 'delete' ? 'del' : method; + const handler = mod[method_export]; + if (handler) { + handler(req, res, next); + } else { + // no matching handler for method — 404 + next(); + } + } + } + + return function find_route(req, res, next) { + const url = req.pathname; + + // whatever happens, we're going to serve some HTML + res.setHeader('Content-Type', 'text/html'); + + resolved + .then(() => { + for (const route of routes) { + if (route.test(url)) return handle_route(route, req, res, next, fn()); + } + + // no matching route — 404 + next(); + }) + .catch(err => { + res.statusCode = 500; + res.end(render(500, { + title: (err && err.name) || 'Internal server error', + url, + error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), + stack: err && err.stack.split('\n').slice(1).join('\n') + })); + }); + }; +} + +function get_not_found_handler(fn) { + return function handle_not_found(req, res) { + const asset_cache = fn(); + + res.statusCode = 404; + res.end(render(404, { + title: 'Not found', + status: 404, + method: req.method, + scripts: ``, + url: req.url + })); + }; +} + +function compose_handlers(handlers) { + return (req, res, next) => { + let i = 0; + function go() { + const handler = handlers[i]; + + if (handler) { + handler(req, res, () => { + i += 1; + go(); + }); + } else { + next(); + } + } + + go(); + }; +} + +function read_json(file) { + return JSON.parse(fs.readFileSync(file, 'utf-8')); +} + +function try_serialize(data) { + try { + return serialize(data); + } catch (err) { + return null; + } +} + +module.exports = index; diff --git a/mocha.opts b/mocha.opts index d68a99b..a1babb5 100644 --- a/mocha.opts +++ b/mocha.opts @@ -1,3 +1,4 @@ +--require ts-node/register --recursive test/unit/**/*.js test/common/test.js \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index aae8adf..4907693 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,36 @@ { "name": "sapper", - "version": "0.4.0", + "version": "0.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { + "@std/esm": { + "version": "0.19.7", + "resolved": "https://registry.npmjs.org/@std/esm/-/esm-0.19.7.tgz", + "integrity": "sha512-bPBbpu1vqgOOD70aMVG5tgioPdttKXQQFq6xodjZxVbPprtZIcm8NcTEJoB+/1QoH8z1TIqjaEN1Wm3YndnfNQ==", + "dev": true + }, "@types/node": { - "version": "7.0.52", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.52.tgz", - "integrity": "sha512-jjpyQsKGsOF/wUElNjfPULk+d8PKvJOIXk3IUeBYYmNCy5dMWfrI+JiixYNw8ppKOlcRwWTXFl0B+i5oGrf95Q==" + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.3.0.tgz", + "integrity": "sha512-wNBfvNjzsJl4tswIZKXCFQY0lss9nKUyJnG6T94X/eqjRgI2jHZ4evdjhQYBSan/vGtF6XVXPApOmNH2rf0KKw==" + }, + "@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", + "dev": true + }, + "@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true }, "accepts": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "dev": true, "requires": { "mime-types": "2.1.17", "negotiator": "0.6.1" @@ -158,8 +175,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "array-map": { "version": "0.0.0", @@ -255,7 +271,7 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000791", + "caniuse-db": "1.0.30000793", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "5.2.18", @@ -351,7 +367,6 @@ "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, "requires": { "bytes": "3.0.0", "content-type": "1.0.4", @@ -363,17 +378,6 @@ "qs": "6.5.1", "raw-body": "2.3.2", "type-is": "1.6.15" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "boolbase": { @@ -490,8 +494,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000791", - "electron-to-chromium": "1.3.30" + "caniuse-db": "1.0.30000793", + "electron-to-chromium": "1.3.31" } }, "buffer": { @@ -522,8 +526,7 @@ "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "caller-path": { "version": "0.1.0", @@ -570,15 +573,15 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000791", + "caniuse-db": "1.0.30000793", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" } }, "caniuse-db": { - "version": "1.0.30000791", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000791.tgz", - "integrity": "sha1-Bnh/VsrvQwChfjXRN0RxI731Nvk=", + "version": "1.0.30000793", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000793.tgz", + "integrity": "sha1-PADGbkI6ehkHx92Wdpp4sq+opy4=", "dev": true }, "caseless": { @@ -859,26 +862,22 @@ "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "core-js": { "version": "2.5.3", @@ -979,9 +978,9 @@ "dev": true }, "css-loader": { - "version": "0.28.8", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.8.tgz", - "integrity": "sha512-4jGj7Ag6WUZ5lQyE4te9sJLn0lgkz6HI3WDE4aw98AkW1IAKXPP4blTpPeorlLDpNsYvojo0SYgRJOdz2KbuAw==", + "version": "0.28.9", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.9.tgz", + "integrity": "sha512-r3dgelMm/mkPz5Y7m9SeiGE46i2VsEU/OYbez+1llfxtv8b2y5/b5StaeEvPK3S5tlNQI+tDW/xDIhKJoZgDtw==", "dev": true, "requires": { "babel-code-frame": "6.26.0", @@ -992,7 +991,7 @@ "lodash.camelcase": "4.3.0", "object-assign": "4.1.1", "postcss": "5.2.18", - "postcss-modules-extract-imports": "1.1.0", + "postcss-modules-extract-imports": "1.2.0", "postcss-modules-local-by-default": "1.2.0", "postcss-modules-scope": "1.1.0", "postcss-modules-values": "1.3.0", @@ -1097,7 +1096,7 @@ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "dashdash": { @@ -1115,10 +1114,9 @@ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } @@ -1214,8 +1212,7 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "des.js": { "version": "1.0.0", @@ -1229,8 +1226,7 @@ "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "diff": { "version": "3.3.1", @@ -1319,8 +1315,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron": { "version": "1.7.10", @@ -1331,6 +1326,14 @@ "@types/node": "7.0.52", "electron-download": "3.3.0", "extract-zip": "1.6.6" + }, + "dependencies": { + "@types/node": { + "version": "7.0.52", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.52.tgz", + "integrity": "sha512-jjpyQsKGsOF/wUElNjfPULk+d8PKvJOIXk3IUeBYYmNCy5dMWfrI+JiixYNw8ppKOlcRwWTXFl0B+i5oGrf95Q==", + "dev": true + } } }, "electron-download": { @@ -1345,20 +1348,11 @@ "minimist": "1.2.0", "nugget": "2.0.1", "path-exists": "2.1.0", - "rc": "1.2.3", - "semver": "5.4.1", + "rc": "1.2.4", + "semver": "5.5.0", "sumchecker": "1.3.1" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -1376,20 +1370,11 @@ } } }, - "electron-releases": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/electron-releases/-/electron-releases-2.1.0.tgz", - "integrity": "sha512-cyKFD1bTE/UgULXfaueIN1k5EPFzs+FRc/rvCY5tIynefAPqopQEgjr0EzY+U3Dqrk/G4m9tXSPuZ77v6dL/Rw==", - "dev": true - }, "electron-to-chromium": { - "version": "1.3.30", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz", - "integrity": "sha512-zx1Prv7kYLfc4OA60FhxGbSo4qrEjgSzpo1/37i7l9ltXPYOoQBtjQxY9KmsgfHnBxHlBGXwLlsbt/gub1w5lw==", - "dev": true, - "requires": { - "electron-releases": "2.1.0" - } + "version": "1.3.31", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz", + "integrity": "sha512-XE4CLbswkZgZFn34cKFy1xaX+F5LHxeDLjY1+rsK9asDzknhbrd9g/n/01/acbU25KTsUSiLKwvlLyA+6XLUOA==", + "dev": true }, "elliptic": { "version": "6.4.0", @@ -1413,14 +1398,12 @@ "encodeurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", - "dev": true + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" }, "encoding": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, "requires": { "iconv-lite": "0.4.19" } @@ -1504,9 +1487,9 @@ } }, "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "version": "0.10.38", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", + "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", "requires": { "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" @@ -1518,7 +1501,7 @@ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-symbol": "3.1.1" } }, @@ -1528,7 +1511,7 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-iterator": "2.0.3", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -1547,7 +1530,7 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -1559,7 +1542,7 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "es6-weak-map": { @@ -1568,7 +1551,7 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -1595,9 +1578,9 @@ } }, "eslint": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.15.0.tgz", - "integrity": "sha512-zEO/Z1ZUxIQ+MhDVKkVTUYpIPDTEJLXGMrkID+5v1NeQHtCz6FZikWuFRgxE1Q/RV2V4zVl1u3xmpPADHhMZ6A==", + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.16.0.tgz", + "integrity": "sha512-YVXV4bDhNoHHcv0qzU4Meof7/P26B4EuaktMi5L1Tnt52Aov85KmYA8c5D+xyZr/BkhvwUqr011jDSD/QTULxg==", "dev": true, "requires": { "ajv": "5.5.2", @@ -1632,7 +1615,7 @@ "pluralize": "7.0.0", "progress": "2.0.0", "require-uncached": "1.0.3", - "semver": "5.4.1", + "semver": "5.5.0", "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", "table": "4.0.2", @@ -1645,6 +1628,15 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", @@ -1680,17 +1672,6 @@ "requires": { "debug": "2.6.9", "resolve": "1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "eslint-module-utils": { @@ -1701,17 +1682,6 @@ "requires": { "debug": "2.6.9", "pkg-dir": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "eslint-plugin-import": { @@ -1732,15 +1702,6 @@ "read-pkg-up": "2.0.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", @@ -1823,8 +1784,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "event-emitter": { "version": "0.3.5", @@ -1832,7 +1792,7 @@ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "event-stream": { @@ -1898,7 +1858,6 @@ "version": "4.16.2", "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", - "dev": true, "requires": { "accepts": "1.3.4", "array-flatten": "1.1.1", @@ -1930,17 +1889,6 @@ "type-is": "1.6.15", "utils-merge": "1.0.1", "vary": "1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "extend": { @@ -1980,15 +1928,6 @@ "yauzl": "2.4.1" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "mkdirp": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", @@ -2077,7 +2016,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "1.0.1", @@ -2086,17 +2024,6 @@ "parseurl": "1.3.2", "statuses": "1.3.1", "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "find-up": { @@ -2164,14 +2091,12 @@ "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "from": { "version": "0.1.7", @@ -3192,6 +3117,15 @@ "integrity": "sha1-eIspgVsS1Tus9XVkhHbm+QQdEz8=", "dev": true }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", @@ -3225,7 +3159,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, "requires": { "depd": "1.1.1", "inherits": "2.0.3", @@ -3236,14 +3169,12 @@ "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" } } }, @@ -3266,8 +3197,7 @@ "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "icss-replace-symbols": { "version": "1.1.0", @@ -3421,8 +3351,7 @@ "ipaddr.js": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", - "dev": true + "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" }, "is-absolute-url": { "version": "2.1.0", @@ -3667,9 +3596,9 @@ } }, "js-base64": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz", - "integrity": "sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.1.tgz", + "integrity": "sha512-2h586r2I/CqU7z1aa1kBgWaVAXWAZK+zHnceGi/jFgn7+7VSluxYer/i3xOZVearCxxXvyDkLtTBo+OeJCA3kA==", "dev": true }, "js-tokens": { @@ -3917,6 +3846,12 @@ "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", "dev": true }, + "make-error": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.2.tgz", + "integrity": "sha512-l9ra35l5VWLF24y75Tg8XgfGLX0ueRhph118WKM6H5denx4bB5QF59+4UAm9oJ2qsPQZas/CQUDdtDdfvYHBdQ==", + "dev": true + }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -3966,8 +3901,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { "version": "1.1.0", @@ -4094,14 +4028,12 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "2.3.11", @@ -4135,20 +4067,17 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" }, "mime-types": { "version": "2.1.17", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, "requires": { "mime-db": "1.30.0" } @@ -4227,6 +4156,15 @@ "supports-color": "4.4.0" }, "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4247,8 +4185,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mute-stream": { "version": "0.0.7", @@ -4271,8 +4208,7 @@ "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "nightmare": { "version": "2.10.0", @@ -4293,24 +4229,12 @@ "rimraf": "2.6.2", "sliced": "1.0.1", "split2": "2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, "requires": { "encoding": "0.1.12", "is-stream": "1.1.0" @@ -4337,7 +4261,7 @@ "querystring-es3": "0.2.1", "readable-stream": "2.3.3", "stream-browserify": "2.0.1", - "stream-http": "2.7.2", + "stream-http": "2.8.0", "string_decoder": "1.0.3", "timers-browserify": "2.0.4", "tty-browserify": "0.0.0", @@ -4353,7 +4277,7 @@ "requires": { "hosted-git-info": "2.5.0", "is-builtin-module": "1.0.0", - "semver": "5.4.1", + "semver": "5.5.0", "validate-npm-package-license": "3.0.1" } }, @@ -4481,15 +4405,6 @@ "throttleit": "0.0.2" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -4539,7 +4454,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -4666,19 +4580,24 @@ "error-ex": "1.3.1" } }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, "parse5": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "requires": { - "@types/node": "7.0.52" + "@types/node": "9.3.0" } }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, "path-browserify": { "version": "0.0.0", @@ -4715,8 +4634,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { "version": "2.0.0", @@ -4822,7 +4740,7 @@ "dev": true, "requires": { "chalk": "1.1.3", - "js-base64": "2.4.0", + "js-base64": "2.4.1", "source-map": "0.5.7", "supports-color": "3.2.3" }, @@ -5044,9 +4962,9 @@ } }, "postcss-modules-extract-imports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", - "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", + "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", "dev": true, "requires": { "postcss": "6.0.16" @@ -5363,7 +5281,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", - "dev": true, "requires": { "forwarded": "0.1.2", "ipaddr.js": "1.5.2" @@ -5414,8 +5331,7 @@ "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "query-string": { "version": "4.3.4", @@ -5437,6 +5353,11 @@ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" + }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", @@ -5494,14 +5415,12 @@ "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, "requires": { "bytes": "3.0.0", "http-errors": "1.6.2", @@ -5510,9 +5429,9 @@ } }, "rc": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.3.tgz", - "integrity": "sha1-UVdakA+N1oOBxxC0cSwhVMPiA1s=", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.4.tgz", + "integrity": "sha1-oPYGyq4qO4YrvQ74VILAElsxX6M=", "dev": true, "requires": { "deep-extend": "0.4.2", @@ -5718,7 +5637,7 @@ "stringstream": "0.0.5", "tough-cookie": "2.3.3", "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "uuid": "3.2.1" } }, "require-directory": { @@ -5746,6 +5665,11 @@ "resolve-from": "1.0.1" } }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", @@ -5894,15 +5818,14 @@ } }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "send": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "1.1.2", @@ -5917,17 +5840,6 @@ "on-finished": "2.3.0", "range-parser": "1.2.0", "statuses": "1.3.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "serialize-javascript": { @@ -5939,7 +5851,6 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", - "dev": true, "requires": { "encodeurl": "1.0.1", "escape-html": "1.0.3", @@ -5965,8 +5876,7 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "sha.js": { "version": "2.4.9", @@ -6080,6 +5990,23 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, + "source-map-support": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.2.tgz", + "integrity": "sha512-9zHceZbQwERaMK1MiFguvx1dL9GQPLXInr2D/wUxAsuV6ZKc9F0DHYWeloMcalkYRbtanwqUakoDjvj55cL/4A==", + "dev": true, + "requires": { + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "spdx-correct": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", @@ -6159,8 +6086,7 @@ "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" }, "stream-browserify": { "version": "2.0.1", @@ -6181,9 +6107,9 @@ } }, "stream-http": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", "requires": { "builtin-status-codes": "3.0.0", "inherits": "2.0.3", @@ -6303,17 +6229,6 @@ "requires": { "debug": "2.6.9", "es6-promise": "4.2.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "supports-color": { @@ -6325,9 +6240,9 @@ } }, "svelte": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-1.51.1.tgz", - "integrity": "sha512-Uf9huHmtXLzdmkfuEYQeXMvFE9dt8M9/jzujX3/Q2Ek2dzvVz1ARTLP76hlnGqUf4q28w8wfkQxFEx4LgDV5MQ==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-1.53.0.tgz", + "integrity": "sha512-0Hfv3Ez7IH0X69EXyvAo2PpmvdNU7CfmAjDuDJuzvf5Jk69FKmC9HexKNqiN6UvnLjkoHCaZK3SI+A0Q+5/odA==", "dev": true }, "svelte-loader": { @@ -6500,10 +6415,48 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "ts-node": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-4.1.0.tgz", + "integrity": "sha512-xcZH12oVg9PShKhy3UHyDmuDLV3y7iKwX25aMVPt1SIXSuAfWkFiGPEkg+th8R4YKW/QCxDoW7lJdb15lx6QWg==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "chalk": "2.3.0", + "diff": "3.3.1", + "make-error": "1.3.2", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.5.2", + "tsconfig": "7.0.0", + "v8flags": "3.0.1", + "yn": "2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "requires": { + "@types/strip-bom": "3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1" + } + }, "tslib": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", - "integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", "dev": true }, "tty-browserify": { @@ -6540,7 +6493,6 @@ "version": "1.6.15", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "2.1.17" @@ -6621,8 +6573,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "url": { "version": "0.11.0", @@ -6640,6 +6591,15 @@ } } }, + "url-parse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + } + }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -6663,15 +6623,23 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, + "v8flags": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.1.tgz", + "integrity": "sha1-3Oj8N5wX2fLJ6e142JzgAFKxt2s=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", @@ -6684,8 +6652,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "vendors": { "version": "1.0.1", @@ -6959,6 +6926,12 @@ "requires": { "fd-slicer": "1.0.1" } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true } } } diff --git a/package.json b/package.json index 8501e75..360d881 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,13 @@ "name": "sapper", "version": "0.5.1", "description": "Military-grade apps, engineered by Svelte", - "main": "lib/index.js", + "main": "middleware.js", "bin": { "sapper": "cli/index.js" }, "files": [ - "cli", - "lib", + "cli.js", + "middleware.js", "runtime", "runtime.js", "webpack" @@ -22,8 +22,11 @@ "chokidar": "^1.7.0", "code-frame": "^5.0.0", "escape-html": "^1.0.3", + "express": "^4.16.2", + "glob": "^7.1.2", "locate-character": "^2.0.5", "mkdirp": "^0.5.1", + "node-fetch": "^1.7.3", "relative": "^3.0.2", "require-relative": "^0.8.7", "rimraf": "^2.6.2", @@ -35,20 +38,20 @@ "webpack-hot-middleware": "^2.21.0" }, "devDependencies": { + "@std/esm": "^0.19.7", "css-loader": "^0.28.7", "eslint": "^4.13.1", "eslint-plugin-import": "^2.8.0", - "express": "^4.16.2", "get-port": "^3.2.0", "mocha": "^4.0.1", "nightmare": "^2.10.0", - "node-fetch": "^1.7.3", "npm-run-all": "^4.1.2", "rollup": "^0.53.0", "rollup-plugin-typescript": "^0.8.1", "style-loader": "^0.19.1", "svelte": "^1.49.1", "svelte-loader": "^2.3.2", + "ts-node": "^4.1.0", "tslib": "^1.8.1", "typescript": "^2.6.2", "wait-on": "^2.0.2" diff --git a/rollup.config.js b/rollup.config.js index 77a4f03..8074091 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,59 @@ import typescript from 'rollup-plugin-typescript'; +import pkg from './package.json'; + +const external = [].concat( + Object.keys(pkg.dependencies), + Object.keys(process.binding('natives')) +); export default [ + // cli.js + { + input: 'src/cli/index.js', + output: { + file: 'cli.js', + format: 'cjs', + banner: '#!/usr/bin/env node' + }, + external, + plugins: [ + typescript({ + typescript: require('typescript') + }) + ] + }, + + // core.js + // { + // input: 'src/core/index.js', + // output: { + // file: 'core.js', + // format: 'cjs', + // banner: '#!/usr/bin/env node' + // }, + // external, + // plugins: [ + // typescript({ + // typescript: require('typescript') + // }) + // ] + // }, + + // middleware.js + { + input: 'src/middleware/index.js', + output: { + file: 'middleware.js', + format: 'cjs' + }, + external, + plugins: [ + typescript({ + typescript: require('typescript') + }) + ] + }, + // runtime.js { input: 'src/runtime/index.ts', @@ -8,6 +61,22 @@ export default [ file: 'runtime.js', format: 'es' }, + external, + plugins: [ + typescript({ + typescript: require('typescript') + }) + ] + }, + + // webpack/config.js + { + input: 'src/webpack/index.js', + output: { + file: 'webpack/config.js', + format: 'cjs' + }, + external, plugins: [ typescript({ typescript: require('typescript') diff --git a/runtime/README.md b/runtime/README.md new file mode 100644 index 0000000..7b650d6 --- /dev/null +++ b/runtime/README.md @@ -0,0 +1 @@ +This directory exists for legacy reasons and should be deleted before releasing version 1. \ No newline at end of file diff --git a/cli/index.js b/src/cli/index.js similarity index 85% rename from cli/index.js rename to src/cli/index.js index afd006a..1999207 100755 --- a/cli/index.js +++ b/src/cli/index.js @@ -1,6 +1,5 @@ -#!/usr/bin/env node - -const build = require('../lib/build.js'); +import build from '../shared/build.js'; +import exporter from '../shared/export.js'; const cmd = process.argv[2]; const start = Date.now(); @@ -18,7 +17,7 @@ if (cmd === 'build') { const start = Date.now(); build() - .then(() => require('../lib/utils/export.js')()) + .then(() => exporter()) .then(() => { const elapsed = Date.now() - start; console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..35f2d33 --- /dev/null +++ b/src/config.js @@ -0,0 +1,21 @@ +import * as path from 'path'; +import mkdirp from 'mkdirp'; +import rimraf from 'rimraf'; + +export const dev = process.env.NODE_ENV !== 'production'; + +export const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); + +export const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); + +export const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); + +if (dev) { + mkdirp.sync(dest); + rimraf.sync(path.join(dest, '**/*')); +} + +export const entry = { + client: path.resolve(templates, '.main.rendered.js'), + server: path.resolve(dest, 'server-entry.js') +}; \ No newline at end of file diff --git a/lib/index.js b/src/middleware/index.js similarity index 91% rename from lib/index.js rename to src/middleware/index.js index 8b3648a..87b24b6 100644 --- a/lib/index.js +++ b/src/middleware/index.js @@ -1,14 +1,14 @@ -const fs = require('fs'); -const path = require('path'); -const serialize = require('serialize-javascript'); -const route_manager = require('./route_manager.js'); -const templates = require('./templates.js'); -const create_app = require('./utils/create_app.js'); -const create_watcher = require('./utils/create_watcher.js'); -const compilers = require('./utils/compilers.js'); -const generate_asset_cache = require('./utils/generate_asset_cache.js'); -const escape_html = require('escape-html'); -const { dest, dev } = require('./config.js'); +import * as fs from 'fs'; +import * as path from 'path'; +import serialize from 'serialize-javascript'; +import escape_html from 'escape-html'; +import * as route_manager from '../shared/route_manager.js'; +import * as templates from '../shared/templates.js'; +import create_app from '../shared/utils/create_app.js'; +import create_watcher from '../shared/utils/create_watcher.js'; +import * as compilers from '../shared/utils/compilers.js'; +import generate_asset_cache from '../shared/generate_asset_cache.js'; +import { dest, dev } from '../config.js'; function connect_dev() { create_app(); @@ -109,7 +109,7 @@ function connect_prod() { return middleware; } -module.exports = dev ? connect_dev : connect_prod; +export default dev ? connect_dev : connect_prod; function set_req_pathname(req, res, next) { req.pathname = req.url.replace(/\?.+/, ''); diff --git a/src/middleware/tmp.json b/src/middleware/tmp.json new file mode 100644 index 0000000..1f3ea02 --- /dev/null +++ b/src/middleware/tmp.json @@ -0,0 +1,154 @@ +[ + { + "x": 1979, + "y": 7.19 + }, + { + "x": 1980, + "y": 7.83 + }, + { + "x": 1981, + "y": 7.24 + }, + { + "x": 1982, + "y": 7.44 + }, + { + "x": 1983, + "y": 7.51 + }, + { + "x": 1984, + "y": 7.1 + }, + { + "x": 1985, + "y": 6.91 + }, + { + "x": 1986, + "y": 7.53 + }, + { + "x": 1987, + "y": 7.47 + }, + { + "x": 1988, + "y": 7.48 + }, + { + "x": 1989, + "y": 7.03 + }, + { + "x": 1990, + "y": 6.23 + }, + { + "x": 1991, + "y": 6.54 + }, + { + "x": 1992, + "y": 7.54 + }, + { + "x": 1993, + "y": 6.5 + }, + { + "x": 1994, + "y": 7.18 + }, + { + "x": 1995, + "y": 6.12 + }, + { + "x": 1996, + "y": 7.87 + }, + { + "x": 1997, + "y": 6.73 + }, + { + "x": 1998, + "y": 6.55 + }, + { + "x": 1999, + "y": 6.23 + }, + { + "x": 2000, + "y": 6.31 + }, + { + "x": 2001, + "y": 6.74 + }, + { + "x": 2002, + "y": 5.95 + }, + { + "x": 2003, + "y": 6.13 + }, + { + "x": 2004, + "y": 6.04 + }, + { + "x": 2005, + "y": 5.56 + }, + { + "x": 2006, + "y": 5.91 + }, + { + "x": 2007, + "y": 4.29 + }, + { + "x": 2008, + "y": 4.72 + }, + { + "x": 2009, + "y": 5.38 + }, + { + "x": 2010, + "y": 4.92 + }, + { + "x": 2011, + "y": 4.61 + }, + { + "x": 2012, + "y": 3.62 + }, + { + "x": 2013, + "y": 5.35 + }, + { + "x": 2014, + "y": 5.28 + }, + { + "x": 2015, + "y": 4.63 + }, + { + "x": 2016, + "y": 4.72 + } + ] \ No newline at end of file diff --git a/lib/build.js b/src/shared/build.js similarity index 72% rename from lib/build.js rename to src/shared/build.js index 445a0ce..3f18d0a 100644 --- a/lib/build.js +++ b/src/shared/build.js @@ -1,15 +1,15 @@ process.env.NODE_ENV = 'production'; -const fs = require('fs'); -const path = require('path'); -const mkdirp = require('mkdirp'); -const rimraf = require('rimraf'); -const { client, server } = require('./utils/compilers.js'); -const create_app = require('./utils/create_app.js'); -const generate_asset_cache = require('./utils/generate_asset_cache.js'); -const { dest } = require('./config.js'); +import * as fs from 'fs'; +import * as path from 'path'; +import mkdirp from 'mkdirp'; +import rimraf from 'rimraf'; +import { client, server } from './utils/compilers.js'; +import create_app from './utils/create_app.js'; +import generate_asset_cache from './generate_asset_cache.js'; +import { dest } from '../config.js'; -module.exports = () => { +export default () => { mkdirp.sync(dest); rimraf.sync(path.join(dest, '**/*')); diff --git a/lib/utils/export.js b/src/shared/export.js similarity index 82% rename from lib/utils/export.js rename to src/shared/export.js index 0b9cb26..b13ea45 100644 --- a/lib/utils/export.js +++ b/src/shared/export.js @@ -1,22 +1,24 @@ -const path = require('path'); -const sander = require('sander'); -const app = require('express')(); -const cheerio = require('cheerio'); -const fetch = require('node-fetch'); -const URL = require('url-parse'); -const generate_asset_cache = require('./generate_asset_cache.js'); -const sapper = require('../index.js'); +import * as path from 'path'; +import * as sander from 'sander'; +import express from 'express'; +import cheerio from 'cheerio'; +import fetch from 'node-fetch'; +import URL from 'url-parse'; +import generate_asset_cache from './generate_asset_cache.js'; +import { dest } from '../config.js'; +import middleware from '../middleware/index.js'; const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env; -const { dest } = require('../config.js'); const origin = `http://localhost:${PORT}`; +const app = express(); + function read_json(file) { return JSON.parse(sander.readFileSync(file, { encoding: 'utf-8' })); } -module.exports = function() { +export default function() { // Prep output directory sander.rimrafSync(OUTPUT_DIR); @@ -60,7 +62,7 @@ module.exports = function() { return fetch(url, opts); }; - app.use(sapper()); + app.use(middleware()); const server = app.listen(PORT); const seen = new Set(); @@ -95,4 +97,4 @@ module.exports = function() { return handle(new URL(origin)) // TODO all static routes .then(() => server.close()); -}; +} \ No newline at end of file diff --git a/lib/utils/generate_asset_cache.js b/src/shared/generate_asset_cache.js similarity index 85% rename from lib/utils/generate_asset_cache.js rename to src/shared/generate_asset_cache.js index d0143c7..91ae425 100644 --- a/lib/utils/generate_asset_cache.js +++ b/src/shared/generate_asset_cache.js @@ -1,15 +1,15 @@ -const fs = require('fs'); -const path = require('path'); -const glob = require('glob'); -const templates = require('../templates.js'); -const route_manager = require('../route_manager.js'); -const { dest, dev } = require('../config.js'); +import * as fs from 'fs'; +import * as path from 'path'; +import glob from 'glob'; +import * as templates from './templates.js'; +import * as route_manager from './route_manager.js'; +import { dest, dev } from '../config.js'; function ensure_array(thing) { return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing } -module.exports = function generate_asset_cache(clientInfo, serverInfo) { +export default function generate_asset_cache(clientInfo, serverInfo) { const main_file = `/client/${ensure_array(clientInfo.assetsByChunkName.main)[0]}`; const chunk_files = clientInfo.assets.map(chunk => `/client/${chunk.name}`); @@ -48,7 +48,7 @@ module.exports = function generate_asset_cache(clientInfo, serverInfo) { service_worker }; -}; +} function generate_service_worker(chunk_files) { const assets = glob.sync('**', { cwd: 'assets', nodir: true }); diff --git a/src/shared/index.js b/src/shared/index.js new file mode 100644 index 0000000..98c7757 --- /dev/null +++ b/src/shared/index.js @@ -0,0 +1,7 @@ +import * as route_manager from './route_manager.js'; +import * as templates from './templates.js'; + +export { default as build } from './build.js'; +export { default as export } from './export.js'; +export { default as generate_asset_cache } from './generate_asset_cache.js'; +export { route_manager, templates }; \ No newline at end of file diff --git a/lib/route_manager.js b/src/shared/route_manager.js similarity index 66% rename from lib/route_manager.js rename to src/shared/route_manager.js index 7f0f9a2..9efe5b9 100644 --- a/lib/route_manager.js +++ b/src/shared/route_manager.js @@ -1,15 +1,17 @@ -const glob = require('glob'); -const create_routes = require('./utils/create_routes.js'); -const { src, dev } = require('./config.js'); +import glob from 'glob'; +import create_routes from './utils/create_routes.js'; +import { src, dev } from '../config.js'; const callbacks = []; -exports.onchange = fn => { +export function onchange(fn) { callbacks.push(fn); -}; +} + +export let routes; function update() { - exports.routes = create_routes( + routes = create_routes( glob.sync('**/*.+(html|js|mjs)', { cwd: src }) ); diff --git a/lib/templates.js b/src/shared/templates.js similarity index 91% rename from lib/templates.js rename to src/shared/templates.js index 9568d50..216783c 100644 --- a/lib/templates.js +++ b/src/shared/templates.js @@ -1,9 +1,9 @@ -const fs = require('fs'); -const glob = require('glob'); -const chalk = require('chalk'); -const framer = require('code-frame'); -const { locate } = require('locate-character'); -const { dev } = require('./config.js'); +import * as fs from 'fs'; +import glob from 'glob'; +import chalk from 'chalk'; +import framer from 'code-frame'; +import { locate } from 'locate-character'; +import { dev } from '../config.js'; let templates; @@ -112,16 +112,16 @@ if (dev) { watcher.on('unlink', create_templates); } -exports.render = (status, data) => { +export function render(status, data) { const template = templates.find(template => template.test(status)); if (template) return template.render(data); return `Missing template for status code ${status}`; -}; +} -exports.stream = (res, status, data) => { +export function stream(res, status, data) { const template = templates.find(template => template.test(status)); if (template) return template.stream(res, data); return `Missing template for status code ${status}`; -}; +} diff --git a/lib/utils/compilers.js b/src/shared/utils/compilers.js similarity index 54% rename from lib/utils/compilers.js rename to src/shared/utils/compilers.js index 58bf7d2..3def12e 100644 --- a/lib/utils/compilers.js +++ b/src/shared/utils/compilers.js @@ -1,11 +1,12 @@ -const path = require('path'); -const relative = require('require-relative'); +import * as path from 'path'; +import relative from 'require-relative'; + const webpack = relative('webpack', process.cwd()); -exports.client = webpack( +export const client = webpack( require(path.resolve('webpack.client.config.js')) ); -exports.server = webpack( +export const server = webpack( require(path.resolve('webpack.server.config.js')) ); \ No newline at end of file diff --git a/lib/utils/create_app.js b/src/shared/utils/create_app.js similarity index 92% rename from lib/utils/create_app.js rename to src/shared/utils/create_app.js index e4da699..6fcb64e 100644 --- a/lib/utils/create_app.js +++ b/src/shared/utils/create_app.js @@ -1,7 +1,7 @@ -const fs = require('fs'); -const path = require('path'); -const route_manager = require('../route_manager.js'); -const { src, entry, dev } = require('../config.js'); +import * as fs from 'fs'; +import * as path from 'path'; +import * as route_manager from '../route_manager.js'; +import { src, entry, dev } from '../../config.js'; function posixify(file) { return file.replace(/[/\\]/g, '/'); @@ -79,4 +79,4 @@ if (dev) { watcher.on('unlink', create_app); } -module.exports = create_app; +export default create_app; diff --git a/lib/utils/create_routes.js b/src/shared/utils/create_routes.js similarity index 95% rename from lib/utils/create_routes.js rename to src/shared/utils/create_routes.js index 8e4122f..97b6d09 100644 --- a/lib/utils/create_routes.js +++ b/src/shared/utils/create_routes.js @@ -1,6 +1,6 @@ -const path = require('path'); +import * as path from 'path'; -module.exports = function create_matchers(files) { +export default function create_matchers(files) { const routes = files .map(file => { if (/(^|\/|\\)_/.test(file)) return; @@ -87,4 +87,4 @@ module.exports = function create_matchers(files) { }); return routes; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/lib/utils/create_watcher.js b/src/shared/utils/create_watcher.js similarity index 83% rename from lib/utils/create_watcher.js rename to src/shared/utils/create_watcher.js index b4ed3bf..c0f3c34 100644 --- a/lib/utils/create_watcher.js +++ b/src/shared/utils/create_watcher.js @@ -1,9 +1,9 @@ -const fs = require('fs'); -const path = require('path'); -const chalk = require('chalk'); -const compilers = require('./compilers.js'); -const generate_asset_cache = require('./generate_asset_cache.js'); -const { dest } = require('../config.js'); +import * as fs from 'fs'; +import * as path from 'path'; +import chalk from 'chalk'; +import * as compilers from './compilers.js'; +import generate_asset_cache from '../../shared/generate_asset_cache.js'; +import { dest } from '../../config.js'; function deferred() { const d = {}; @@ -16,7 +16,7 @@ function deferred() { return d; } -module.exports = function create_watcher() { +export default function create_watcher() { const deferreds = { client: deferred(), server: deferred() @@ -72,4 +72,4 @@ module.exports = function create_watcher() { }; return watcher; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/webpack/index.js b/src/webpack/index.js new file mode 100644 index 0000000..5c50bab --- /dev/null +++ b/src/webpack/index.js @@ -0,0 +1,44 @@ +import { dest, dev, entry } from '../config.js'; + +export default { + dev, + + client: { + entry: () => { + return { + main: [ + entry.client, + // workaround for https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456 + 'style-loader/lib/addStyles', + 'css-loader/lib/css-base' + ] + }; + }, + + output: () => { + return { + path: `${dest}/client`, + filename: '[name].[hash].js', + chunkFilename: '[name].[id].[hash].js', + publicPath: '/client/' + }; + } + }, + + server: { + entry: () => { + return { + main: entry.server + }; + }, + + output: () => { + return { + path: `${dest}/server`, + filename: '[name].[hash].js', + chunkFilename: '[name].[id].[hash].js', + libraryTarget: 'commonjs2' + }; + } + } +}; diff --git a/test/common/test.js b/test/common/test.js index cd56f9a..efe7216 100644 --- a/test/common/test.js +++ b/test/common/test.js @@ -1,11 +1,18 @@ -const path = require('path'); -const assert = require('assert'); +import * as path from 'path'; +import * as assert from 'assert'; + +// import express from 'express'; +// import Nightmare from 'nightmare'; +// import serve from 'serve-static'; +// import walkSync from 'walk-sync'; +// import fetch from 'node-fetch'; + +// TODO reintegrate these as imports +const Nightmare = require('nightmare'); const express = require('express'); const serve = require('serve-static'); -const Nightmare = require('nightmare'); -const getPort = require('get-port'); -const fetch = require('node-fetch'); const walkSync = require('walk-sync'); +const fetch = require('node-fetch'); run('production'); run('development'); @@ -82,7 +89,7 @@ function run(env) { let sapper; if (env === 'production') { - const cli = path.resolve(__dirname, '../../cli/index.js'); + const cli = path.resolve(__dirname, '../../cli.js'); exec_promise = exec(`node ${cli} export`); } @@ -91,7 +98,7 @@ function run(env) { delete require.cache[resolved]; sapper = require(resolved); - return getPort(); + return require('get-port')(); }).then(port => { PORT = port; base = `http://localhost:${PORT}`; diff --git a/test/unit/create_routes.test.js b/test/unit/create_routes.test.js index 3589db6..cbc4856 100644 --- a/test/unit/create_routes.test.js +++ b/test/unit/create_routes.test.js @@ -1,7 +1,6 @@ -const path = require('path'); -const assert = require('assert'); +import * as assert from 'assert'; -const create_routes = require('../../lib/utils/create_routes.js'); +import create_routes from '../../src/shared/utils/create_routes.js'; describe('create_routes', () => { it('sorts routes correctly', () => { diff --git a/webpack/config.js b/webpack/config.js index ae0aed2..0b51e8e 100644 --- a/webpack/config.js +++ b/webpack/config.js @@ -1,6 +1,30 @@ -const { dest, dev, entry } = require('../lib/config.js'); +'use strict'; -module.exports = { +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var path = require('path'); +var mkdirp = _interopDefault(require('mkdirp')); +var rimraf = _interopDefault(require('rimraf')); + +const dev = process.env.NODE_ENV !== 'production'; + +const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); + +const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); + +const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); + +if (dev) { + mkdirp.sync(dest); + rimraf.sync(path.join(dest, '**/*')); +} + +const entry = { + client: path.resolve(templates, '.main.rendered.js'), + server: path.resolve(dest, 'server-entry.js') +}; + +var index = { dev, client: { @@ -42,3 +66,5 @@ module.exports = { } } }; + +module.exports = index; diff --git a/webpack/hmr.js b/webpack/hmr.js deleted file mode 100644 index 39cb639..0000000 --- a/webpack/hmr.js +++ /dev/null @@ -1 +0,0 @@ -import 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000'; \ No newline at end of file From 7d721abb2ab8d7d4b566d777290abc8731bcd46c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 11:15:32 -0500 Subject: [PATCH 2/9] wip 2 --- .gitignore | 3 + cli.js | 910 +----------------- middleware.js | 452 +-------- rollup.config.js | 40 +- src/cli/index.js | 3 +- src/{shared => core}/build.js | 0 src/{shared => core}/export.js | 0 src/{shared => core}/generate_asset_cache.js | 0 src/{shared => core}/index.js | 5 +- src/{shared => core}/route_manager.js | 0 src/{shared => core}/templates.js | 0 src/{shared => core}/utils/compilers.js | 0 src/{shared => core}/utils/create_app.js | 0 src/{shared => core}/utils/create_routes.js | 0 .../utils => middleware}/create_watcher.js | 5 +- src/middleware/index.js | 8 +- src/middleware/tmp.json | 154 --- test/unit/create_routes.test.js | 2 +- 18 files changed, 61 insertions(+), 1521 deletions(-) rename src/{shared => core}/build.js (100%) rename src/{shared => core}/export.js (100%) rename src/{shared => core}/generate_asset_cache.js (100%) rename src/{shared => core}/index.js (62%) rename src/{shared => core}/route_manager.js (100%) rename src/{shared => core}/templates.js (100%) rename src/{shared => core}/utils/compilers.js (100%) rename src/{shared => core}/utils/create_app.js (100%) rename src/{shared => core}/utils/create_routes.js (100%) rename src/{shared/utils => middleware}/create_watcher.js (91%) delete mode 100644 src/middleware/tmp.json diff --git a/.gitignore b/.gitignore index a063eeb..13773db 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ cypress/screenshots test/app/.sapper runtime.js yarn.lock +cli.js +middleware.js +core.js \ No newline at end of file diff --git a/cli.js b/cli.js index d5af45d..b89ccba 100644 --- a/cli.js +++ b/cli.js @@ -1,915 +1,13 @@ #!/usr/bin/env node 'use strict'; -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var fs = require('fs'); -var path = require('path'); -var mkdirp = _interopDefault(require('mkdirp')); -var rimraf = _interopDefault(require('rimraf')); -var relative = _interopDefault(require('require-relative')); -var glob = _interopDefault(require('glob')); -var chalk = _interopDefault(require('chalk')); -var framer = _interopDefault(require('code-frame')); -var locateCharacter = require('locate-character'); -var sander = require('sander'); -var express = _interopDefault(require('express')); -var cheerio = _interopDefault(require('cheerio')); -var fetch = _interopDefault(require('node-fetch')); -var URL = _interopDefault(require('url-parse')); -var serialize = _interopDefault(require('serialize-javascript')); -var escape_html = _interopDefault(require('escape-html')); - -const webpack = relative('webpack', process.cwd()); - -const client = webpack( - require(path.resolve('webpack.client.config.js')) -); - -const server = webpack( - require(path.resolve('webpack.server.config.js')) -); - -var compilers = Object.freeze({ - client: client, - server: server -}); - -function create_matchers(files) { - const routes = files - .map(file => { - if (/(^|\/|\\)_/.test(file)) return; - - const parts = file.replace(/\.(html|js|mjs)$/, '').split('/'); // glob output is always posix-style - if (parts[parts.length - 1] === 'index') parts.pop(); - - const id = ( - parts.join('_').replace(/[[\]]/g, '$').replace(/^\d/, '_$&').replace(/[^a-zA-Z0-9_$]/g, '_') - ) || '_'; - - const dynamic = parts - .filter(part => part[0] === '[') - .map(part => part.slice(1, -1)); - - let pattern_string = ''; - let i = parts.length; - let nested = true; - while (i--) { - const part = parts[i]; - const dynamic = part[0] === '['; - - if (dynamic) { - pattern_string = nested ? `(?:\\/([^/]+)${pattern_string})?` : `\\/([^/]+)${pattern_string}`; - } else { - nested = false; - pattern_string = `\\/${part}${pattern_string}`; - } - } - - const pattern = new RegExp(`^${pattern_string}\\/?$`); - - const test = url => pattern.test(url); - - const exec = url => { - const match = pattern.exec(url); - if (!match) return; - - const params = {}; - dynamic.forEach((param, i) => { - params[param] = match[i + 1]; - }); - - return params; - }; - - return { - id, - type: path.extname(file) === '.html' ? 'page' : 'route', - file, - pattern, - test, - exec, - parts, - dynamic - }; - }) - .filter(Boolean) - .sort((a, b) => { - let same = true; - - for (let i = 0; true; i += 1) { - const a_part = a.parts[i]; - const b_part = b.parts[i]; - - if (!a_part && !b_part) { - if (same) throw new Error(`The ${a.file} and ${b.file} routes clash`); - return 0; - } - - if (!a_part) return -1; - if (!b_part) return 1; - - const a_is_dynamic = a_part[0] === '['; - const b_is_dynamic = b_part[0] === '['; - - if (a_is_dynamic === b_is_dynamic) { - if (!a_is_dynamic && a_part !== b_part) same = false; - continue; - } - - return a_is_dynamic ? 1 : -1; - } - }); - - return routes; -} - -const dev = process.env.NODE_ENV !== 'production'; - -const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); - -const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); - -const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); - -if (dev) { - mkdirp.sync(dest); - rimraf.sync(path.join(dest, '**/*')); -} - -const entry = { - client: path.resolve(templates, '.main.rendered.js'), - server: path.resolve(dest, 'server-entry.js') -}; - -const callbacks = []; - -function onchange(fn) { - callbacks.push(fn); -} - -let routes; - -function update() { - routes = create_matchers( - glob.sync('**/*.+(html|js|mjs)', { cwd: src }) - ); - - callbacks.forEach(fn => fn()); -} - -update(); - -if (dev) { - const watcher = require('chokidar').watch(`${src}/**/*.+(html|js|mjs)`, { - ignoreInitial: true, - persistent: false - }); - - watcher.on('add', update); - watcher.on('change', update); - watcher.on('unlink', update); -} - - -var route_manager = Object.freeze({ - onchange: onchange, - get routes () { return routes; } -}); - -function posixify(file) { - return file.replace(/[/\\]/g, '/'); -} - -function create_app() { - const { routes: routes$$1 } = route_manager; - - function create_client_main() { - const template = fs.readFileSync('templates/main.js', 'utf-8'); - - const code = `[${ - routes$$1 - .filter(route => route.type === 'page') - .map(route => { - const params = route.dynamic.length === 0 ? - '{}' : - `{ ${route.dynamic.map((part, i) => `${part}: match[${i + 1}]`).join(', ') } }`; - - const file = posixify(`${src}/${route.file}`); - return `{ pattern: ${route.pattern}, params: match => (${params}), load: () => import(/* webpackChunkName: "${route.id}" */ '${file}') }` - }) - .join(', ') - }]`; - - let main = template - .replace(/__app__/g, posixify(path.resolve(__dirname, '../../runtime/app.js'))) - .replace(/__routes__/g, code) - .replace(/__dev__/g, String(dev)); - - if (dev) { - const hmr_client = posixify(require.resolve(`webpack-hot-middleware/client`)); - main += `\n\nimport('${hmr_client}?path=/__webpack_hmr&timeout=20000'); if (module.hot) module.hot.accept();`; - } - - fs.writeFileSync(entry.client, main); - - // need to fudge the mtime, because webpack is soft in the head - const { atime, mtime } = fs.statSync(entry.client); - fs.utimesSync(entry.client, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); - } - - function create_server_routes() { - const imports = routes$$1 - .map(route => { - const file = posixify(`${src}/${route.file}`); - return route.type === 'page' ? - `import ${route.id} from '${file}';` : - `import * as ${route.id} from '${file}';`; - }) - .join('\n'); - - const exports = `export { ${routes$$1.map(route => route.id)} };`; - - fs.writeFileSync(entry.server, `${imports}\n\n${exports}`); - - const { atime, mtime } = fs.statSync(entry.server); - fs.utimesSync(entry.server, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); - } - - create_client_main(); - create_server_routes(); -} - -if (dev) { - onchange(create_app); - - const watcher = require('chokidar').watch(`templates/main.js`, { - ignoreInitial: true, - persistent: false - }); - - watcher.on('add', create_app); - watcher.on('change', create_app); - watcher.on('unlink', create_app); -} - -let templates$1; - -function error(e) { - if (e.title) console.error(chalk.bold.red(e.title)); - if (e.body) console.error(chalk.red(e.body)); - if (e.url) console.error(chalk.cyan(e.url)); - if (e.frame) console.error(chalk.grey(e.frame)); - - process.exit(1); -} - -function create_templates() { - templates$1 = glob.sync('*.html', { cwd: 'templates' }) - .map(file => { - const template = fs.readFileSync(`templates/${file}`, 'utf-8'); - const status = file.replace('.html', '').toLowerCase(); - - if (!/^[0-9x]{3}$/.test(status)) { - error({ - title: `templates/${file}`, - body: `Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html` - }); - } - - const index = template.indexOf('%sapper.main%'); - if (index !== -1) { - // TODO remove this in a future version - const { line, column } = locateCharacter.locate(template, index, { offsetLine: 1 }); - const frame = framer(template, line, column); - - error({ - title: `templates/${file}`, - body: ``; - - if (serialized) { - return `${main}`; - } - - return main; - }), - html: promise.then(({ rendered }) => rendered.html), - head: promise.then(({ rendered }) => `${rendered.head}`), - styles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `` : '')) - }); - } else { - const { html, head, css } = mod.render(data); - - const page = render(200, { - scripts: ``, - html, - head: `${head}`, - styles: (css && css.code ? `` : '') - }); - - res.end(page); - } - } - - else { - const method = req.method.toLowerCase(); - // 'delete' cannot be exported from a module because it is a keyword, - // so check for 'del' instead - const method_export = method === 'delete' ? 'del' : method; - const handler = mod[method_export]; - if (handler) { - handler(req, res, next); - } else { - // no matching handler for method — 404 - next(); - } - } - } - - return function find_route(req, res, next) { - const url = req.pathname; - - // whatever happens, we're going to serve some HTML - res.setHeader('Content-Type', 'text/html'); - - resolved - .then(() => { - for (const route of routes) { - if (route.test(url)) return handle_route(route, req, res, next, fn()); - } - - // no matching route — 404 - next(); - }) - .catch(err => { - res.statusCode = 500; - res.end(render(500, { - title: (err && err.name) || 'Internal server error', - url, - error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), - stack: err && err.stack.split('\n').slice(1).join('\n') - })); - }); - }; -} - -function get_not_found_handler(fn) { - return function handle_not_found(req, res) { - const asset_cache = fn(); - - res.statusCode = 404; - res.end(render(404, { - title: 'Not found', - status: 404, - method: req.method, - scripts: ``, - url: req.url - })); - }; -} - -function compose_handlers(handlers) { - return (req, res, next) => { - let i = 0; - function go() { - const handler = handlers[i]; - - if (handler) { - handler(req, res, () => { - i += 1; - go(); - }); - } else { - next(); - } - } - - go(); - }; -} - -function read_json$1(file) { - return JSON.parse(fs.readFileSync(file, 'utf-8')); -} - -function try_serialize(data) { - try { - return serialize(data); - } catch (err) { - return null; - } -} - -const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env; - -const origin = `http://localhost:${PORT}`; - -const app = express(); - -function read_json(file) { - return JSON.parse(sander.readFileSync(file, { encoding: 'utf-8' })); -} - -function exporter() { - // Prep output directory - sander.rimrafSync(OUTPUT_DIR); - - const { service_worker } = generate_asset_cache( - read_json(path.join(dest, 'stats.client.json')), - read_json(path.join(dest, 'stats.server.json')) - ); - - sander.copydirSync('assets').to(OUTPUT_DIR); - sander.copydirSync(dest, 'client').to(OUTPUT_DIR, 'client'); - sander.writeFileSync(OUTPUT_DIR, 'service-worker.js', service_worker); - - // Intercept server route fetches - function save(res) { - res = res.clone(); - - return res.text().then(body => { - const { pathname } = new URL(res.url); - let dest$$1 = OUTPUT_DIR + pathname; - - const type = res.headers.get('Content-Type'); - if (type.startsWith('text/html')) dest$$1 += '/index.html'; - - sander.writeFileSync(dest$$1, body); - - return body; - }); - } - - global.fetch = (url, opts) => { - if (url[0] === '/') { - url = `http://localhost:${PORT}${url}`; - - return fetch(url, opts) - .then(r => { - save(r); - return r; - }); - } - - return fetch(url, opts); - }; - - app.use(middleware()); - const server = app.listen(PORT); - - const seen = new Set(); - - function handle(url) { - if (url.origin !== origin) return; - - if (seen.has(url.pathname)) return; - seen.add(url.pathname); - - return fetch(url.href) - .then(r => { - save(r); - return r.text(); - }) - .then(body => { - const $ = cheerio.load(body); - const hrefs = []; - - $('a[href]').each((i, $a) => { - hrefs.push($a.attribs.href); - }); - - return hrefs.reduce((promise, href) => { - return promise.then(() => handle(new URL(href, url.href))); - }, Promise.resolve()); - }) - .catch(err => { - console.error(`Error rendering ${url.pathname}: ${err.message}`); - }); - } - - return handle(new URL(origin)) // TODO all static routes - .then(() => server.close()); -} +var core_js = require('./core.js'); const cmd = process.argv[2]; const start = Date.now(); if (cmd === 'build') { - build() + core_js.build() .then(() => { const elapsed = Date.now() - start; console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' @@ -920,8 +18,8 @@ if (cmd === 'build') { } else if (cmd === 'export') { const start = Date.now(); - build() - .then(() => exporter()) + core_js.build() + .then(() => core_js.export()) .then(() => { const elapsed = Date.now() - start; console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' diff --git a/middleware.js b/middleware.js index c23539e..4ef5712 100644 --- a/middleware.js +++ b/middleware.js @@ -6,106 +6,14 @@ var fs = require('fs'); var path = require('path'); var serialize = _interopDefault(require('serialize-javascript')); var escape_html = _interopDefault(require('escape-html')); -var glob = _interopDefault(require('glob')); +var core_js = require('./core.js'); +var chalk = _interopDefault(require('chalk')); var mkdirp = _interopDefault(require('mkdirp')); var rimraf = _interopDefault(require('rimraf')); -var chalk = _interopDefault(require('chalk')); -var framer = _interopDefault(require('code-frame')); -var locateCharacter = require('locate-character'); -var relative = _interopDefault(require('require-relative')); - -function create_matchers(files) { - const routes = files - .map(file => { - if (/(^|\/|\\)_/.test(file)) return; - - const parts = file.replace(/\.(html|js|mjs)$/, '').split('/'); // glob output is always posix-style - if (parts[parts.length - 1] === 'index') parts.pop(); - - const id = ( - parts.join('_').replace(/[[\]]/g, '$').replace(/^\d/, '_$&').replace(/[^a-zA-Z0-9_$]/g, '_') - ) || '_'; - - const dynamic = parts - .filter(part => part[0] === '[') - .map(part => part.slice(1, -1)); - - let pattern_string = ''; - let i = parts.length; - let nested = true; - while (i--) { - const part = parts[i]; - const dynamic = part[0] === '['; - - if (dynamic) { - pattern_string = nested ? `(?:\\/([^/]+)${pattern_string})?` : `\\/([^/]+)${pattern_string}`; - } else { - nested = false; - pattern_string = `\\/${part}${pattern_string}`; - } - } - - const pattern = new RegExp(`^${pattern_string}\\/?$`); - - const test = url => pattern.test(url); - - const exec = url => { - const match = pattern.exec(url); - if (!match) return; - - const params = {}; - dynamic.forEach((param, i) => { - params[param] = match[i + 1]; - }); - - return params; - }; - - return { - id, - type: path.extname(file) === '.html' ? 'page' : 'route', - file, - pattern, - test, - exec, - parts, - dynamic - }; - }) - .filter(Boolean) - .sort((a, b) => { - let same = true; - - for (let i = 0; true; i += 1) { - const a_part = a.parts[i]; - const b_part = b.parts[i]; - - if (!a_part && !b_part) { - if (same) throw new Error(`The ${a.file} and ${b.file} routes clash`); - return 0; - } - - if (!a_part) return -1; - if (!b_part) return 1; - - const a_is_dynamic = a_part[0] === '['; - const b_is_dynamic = b_part[0] === '['; - - if (a_is_dynamic === b_is_dynamic) { - if (!a_is_dynamic && a_part !== b_part) same = false; - continue; - } - - return a_is_dynamic ? 1 : -1; - } - }); - - return routes; -} const dev = process.env.NODE_ENV !== 'production'; -const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); +const templates$1 = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); @@ -117,332 +25,10 @@ if (dev) { } const entry = { - client: path.resolve(templates, '.main.rendered.js'), + client: path.resolve(templates$1, '.main.rendered.js'), server: path.resolve(dest, 'server-entry.js') }; -const callbacks = []; - -function onchange(fn) { - callbacks.push(fn); -} - -let routes; - -function update() { - routes = create_matchers( - glob.sync('**/*.+(html|js|mjs)', { cwd: src }) - ); - - callbacks.forEach(fn => fn()); -} - -update(); - -if (dev) { - const watcher = require('chokidar').watch(`${src}/**/*.+(html|js|mjs)`, { - ignoreInitial: true, - persistent: false - }); - - watcher.on('add', update); - watcher.on('change', update); - watcher.on('unlink', update); -} - - -var route_manager = Object.freeze({ - onchange: onchange, - get routes () { return routes; } -}); - -let templates$1; - -function error(e) { - if (e.title) console.error(chalk.bold.red(e.title)); - if (e.body) console.error(chalk.red(e.body)); - if (e.url) console.error(chalk.cyan(e.url)); - if (e.frame) console.error(chalk.grey(e.frame)); - - process.exit(1); -} - -function create_templates() { - templates$1 = glob.sync('*.html', { cwd: 'templates' }) - .map(file => { - const template = fs.readFileSync(`templates/${file}`, 'utf-8'); - const status = file.replace('.html', '').toLowerCase(); - - if (!/^[0-9x]{3}$/.test(status)) { - error({ - title: `templates/${file}`, - body: `Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html` - }); - } - - const index = template.indexOf('%sapper.main%'); - if (index !== -1) { - // TODO remove this in a future version - const { line, column } = locateCharacter.locate(template, index, { offsetLine: 1 }); - const frame = framer(template, line, column); - - error({ - title: `templates/${file}`, - body: ``; + const main = ``; if (serialized) { return `${main}`; @@ -669,8 +255,8 @@ function get_route_handler(fn) { } else { const { html, head, css } = mod.render(data); - const page = render(200, { - scripts: ``, + const page = core_js.templates.render(200, { + scripts: ``, html, head: `${head}`, styles: (css && css.code ? `` : '') @@ -703,7 +289,7 @@ function get_route_handler(fn) { resolved .then(() => { - for (const route of routes) { + for (const route of core_js.route_manager.routes) { if (route.test(url)) return handle_route(route, req, res, next, fn()); } @@ -712,7 +298,7 @@ function get_route_handler(fn) { }) .catch(err => { res.statusCode = 500; - res.end(render(500, { + res.end(core_js.templates.render(500, { title: (err && err.name) || 'Internal server error', url, error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), @@ -727,7 +313,7 @@ function get_not_found_handler(fn) { const asset_cache = fn(); res.statusCode = 404; - res.end(render(404, { + res.end(core_js.templates.render(404, { title: 'Not found', status: 404, method: req.method, diff --git a/rollup.config.js b/rollup.config.js index 8074091..c8fae3b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -3,9 +3,14 @@ import pkg from './package.json'; const external = [].concat( Object.keys(pkg.dependencies), - Object.keys(process.binding('natives')) + Object.keys(process.binding('natives')), + 'sapper' ); +const paths = { + 'sapper/core.js': './core.js' +}; + export default [ // cli.js { @@ -16,6 +21,7 @@ export default [ banner: '#!/usr/bin/env node' }, external, + paths, plugins: [ typescript({ typescript: require('typescript') @@ -24,20 +30,21 @@ export default [ }, // core.js - // { - // input: 'src/core/index.js', - // output: { - // file: 'core.js', - // format: 'cjs', - // banner: '#!/usr/bin/env node' - // }, - // external, - // plugins: [ - // typescript({ - // typescript: require('typescript') - // }) - // ] - // }, + { + input: 'src/core/index.js', + output: { + file: 'core.js', + format: 'cjs', + banner: '#!/usr/bin/env node' + }, + external, + paths, + plugins: [ + typescript({ + typescript: require('typescript') + }) + ] + }, // middleware.js { @@ -47,6 +54,7 @@ export default [ format: 'cjs' }, external, + paths, plugins: [ typescript({ typescript: require('typescript') @@ -62,6 +70,7 @@ export default [ format: 'es' }, external, + paths, plugins: [ typescript({ typescript: require('typescript') @@ -77,6 +86,7 @@ export default [ format: 'cjs' }, external, + paths, plugins: [ typescript({ typescript: require('typescript') diff --git a/src/cli/index.js b/src/cli/index.js index 1999207..64478c4 100755 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -1,5 +1,4 @@ -import build from '../shared/build.js'; -import exporter from '../shared/export.js'; +import { build, export as exporter } from 'sapper/core.js'; const cmd = process.argv[2]; const start = Date.now(); diff --git a/src/shared/build.js b/src/core/build.js similarity index 100% rename from src/shared/build.js rename to src/core/build.js diff --git a/src/shared/export.js b/src/core/export.js similarity index 100% rename from src/shared/export.js rename to src/core/export.js diff --git a/src/shared/generate_asset_cache.js b/src/core/generate_asset_cache.js similarity index 100% rename from src/shared/generate_asset_cache.js rename to src/core/generate_asset_cache.js diff --git a/src/shared/index.js b/src/core/index.js similarity index 62% rename from src/shared/index.js rename to src/core/index.js index 98c7757..ced82f2 100644 --- a/src/shared/index.js +++ b/src/core/index.js @@ -1,7 +1,10 @@ import * as route_manager from './route_manager.js'; import * as templates from './templates.js'; +import * as compilers from './utils/compilers.js'; export { default as build } from './build.js'; export { default as export } from './export.js'; export { default as generate_asset_cache } from './generate_asset_cache.js'; -export { route_manager, templates }; \ No newline at end of file +export { default as create_app } from './utils/create_app.js'; + +export { compilers, route_manager, templates }; \ No newline at end of file diff --git a/src/shared/route_manager.js b/src/core/route_manager.js similarity index 100% rename from src/shared/route_manager.js rename to src/core/route_manager.js diff --git a/src/shared/templates.js b/src/core/templates.js similarity index 100% rename from src/shared/templates.js rename to src/core/templates.js diff --git a/src/shared/utils/compilers.js b/src/core/utils/compilers.js similarity index 100% rename from src/shared/utils/compilers.js rename to src/core/utils/compilers.js diff --git a/src/shared/utils/create_app.js b/src/core/utils/create_app.js similarity index 100% rename from src/shared/utils/create_app.js rename to src/core/utils/create_app.js diff --git a/src/shared/utils/create_routes.js b/src/core/utils/create_routes.js similarity index 100% rename from src/shared/utils/create_routes.js rename to src/core/utils/create_routes.js diff --git a/src/shared/utils/create_watcher.js b/src/middleware/create_watcher.js similarity index 91% rename from src/shared/utils/create_watcher.js rename to src/middleware/create_watcher.js index c0f3c34..6ae8f08 100644 --- a/src/shared/utils/create_watcher.js +++ b/src/middleware/create_watcher.js @@ -1,9 +1,8 @@ import * as fs from 'fs'; import * as path from 'path'; import chalk from 'chalk'; -import * as compilers from './compilers.js'; -import generate_asset_cache from '../../shared/generate_asset_cache.js'; -import { dest } from '../../config.js'; +import { compilers, generate_asset_cache } from 'sapper/core.js'; +import { dest } from '../config.js'; function deferred() { const d = {}; diff --git a/src/middleware/index.js b/src/middleware/index.js index 87b24b6..89bb113 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -2,12 +2,8 @@ import * as fs from 'fs'; import * as path from 'path'; import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; -import * as route_manager from '../shared/route_manager.js'; -import * as templates from '../shared/templates.js'; -import create_app from '../shared/utils/create_app.js'; -import create_watcher from '../shared/utils/create_watcher.js'; -import * as compilers from '../shared/utils/compilers.js'; -import generate_asset_cache from '../shared/generate_asset_cache.js'; +import { route_manager, templates, create_app, compilers, generate_asset_cache } from 'sapper/core.js'; +import create_watcher from './create_watcher.js'; import { dest, dev } from '../config.js'; function connect_dev() { diff --git a/src/middleware/tmp.json b/src/middleware/tmp.json deleted file mode 100644 index 1f3ea02..0000000 --- a/src/middleware/tmp.json +++ /dev/null @@ -1,154 +0,0 @@ -[ - { - "x": 1979, - "y": 7.19 - }, - { - "x": 1980, - "y": 7.83 - }, - { - "x": 1981, - "y": 7.24 - }, - { - "x": 1982, - "y": 7.44 - }, - { - "x": 1983, - "y": 7.51 - }, - { - "x": 1984, - "y": 7.1 - }, - { - "x": 1985, - "y": 6.91 - }, - { - "x": 1986, - "y": 7.53 - }, - { - "x": 1987, - "y": 7.47 - }, - { - "x": 1988, - "y": 7.48 - }, - { - "x": 1989, - "y": 7.03 - }, - { - "x": 1990, - "y": 6.23 - }, - { - "x": 1991, - "y": 6.54 - }, - { - "x": 1992, - "y": 7.54 - }, - { - "x": 1993, - "y": 6.5 - }, - { - "x": 1994, - "y": 7.18 - }, - { - "x": 1995, - "y": 6.12 - }, - { - "x": 1996, - "y": 7.87 - }, - { - "x": 1997, - "y": 6.73 - }, - { - "x": 1998, - "y": 6.55 - }, - { - "x": 1999, - "y": 6.23 - }, - { - "x": 2000, - "y": 6.31 - }, - { - "x": 2001, - "y": 6.74 - }, - { - "x": 2002, - "y": 5.95 - }, - { - "x": 2003, - "y": 6.13 - }, - { - "x": 2004, - "y": 6.04 - }, - { - "x": 2005, - "y": 5.56 - }, - { - "x": 2006, - "y": 5.91 - }, - { - "x": 2007, - "y": 4.29 - }, - { - "x": 2008, - "y": 4.72 - }, - { - "x": 2009, - "y": 5.38 - }, - { - "x": 2010, - "y": 4.92 - }, - { - "x": 2011, - "y": 4.61 - }, - { - "x": 2012, - "y": 3.62 - }, - { - "x": 2013, - "y": 5.35 - }, - { - "x": 2014, - "y": 5.28 - }, - { - "x": 2015, - "y": 4.63 - }, - { - "x": 2016, - "y": 4.72 - } - ] \ No newline at end of file diff --git a/test/unit/create_routes.test.js b/test/unit/create_routes.test.js index cbc4856..8c2b291 100644 --- a/test/unit/create_routes.test.js +++ b/test/unit/create_routes.test.js @@ -1,6 +1,6 @@ import * as assert from 'assert'; -import create_routes from '../../src/shared/utils/create_routes.js'; +import create_routes from '../../src/core/utils/create_routes.js'; describe('create_routes', () => { it('sorts routes correctly', () => { From dd8deb2d8a6f3229eefc8c0974b89426cfcdcd17 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 14:41:11 -0500 Subject: [PATCH 3/9] wip 3 --- cli.js | 30 +++++++++++++++++++++++--- cli.js.map | 1 + core.js.map | 1 + middleware.js | 13 +++++++----- middleware.js.map | 1 + mocha.opts | 2 +- package.json | 1 + rollup.config.js | 27 ++++++++++++++---------- runtime.js.map | 1 + src/cli/index.js | 7 ++++--- src/core/build.js | 29 ++++++++++++------------- src/core/export.js | 17 ++++++++------- src/core/generate_asset_cache.js | 19 ++++++++++------- src/core/index.js | 1 + src/core/route_manager.js | 26 +++-------------------- src/core/templates.js | 16 +------------- src/core/utils/compilers.js | 27 ++++++++++++++++++------ src/core/utils/create_app.js | 36 +++++++++++++++++++++++--------- src/core/utils/create_routes.js | 2 +- src/middleware/index.js | 14 +++++++------ test/common/test.js | 16 +++++--------- test/unit/create_routes.test.js | 5 ++--- webpack/config.js | 1 + webpack/config.js.map | 1 + 24 files changed, 166 insertions(+), 128 deletions(-) create mode 100644 cli.js.map create mode 100644 core.js.map create mode 100644 middleware.js.map create mode 100644 runtime.js.map create mode 100644 webpack/config.js.map diff --git a/cli.js b/cli.js index b89ccba..40ec17b 100644 --- a/cli.js +++ b/cli.js @@ -1,13 +1,36 @@ #!/usr/bin/env node 'use strict'; +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + var core_js = require('./core.js'); +var path = require('path'); +var mkdirp = _interopDefault(require('mkdirp')); +var rimraf = _interopDefault(require('rimraf')); + +const dev = process.env.NODE_ENV !== 'production'; + +const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); + +const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); + +const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); + +if (dev) { + mkdirp.sync(dest); + rimraf.sync(path.join(dest, '**/*')); +} + +const entry = { + client: path.resolve(templates, '.main.rendered.js'), + server: path.resolve(dest, 'server-entry.js') +}; const cmd = process.argv[2]; const start = Date.now(); if (cmd === 'build') { - core_js.build() + core_js.build({ dest, dev, entry, src }) .then(() => { const elapsed = Date.now() - start; console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' @@ -18,8 +41,8 @@ if (cmd === 'build') { } else if (cmd === 'export') { const start = Date.now(); - core_js.build() - .then(() => core_js.export()) + core_js.build({ dest, dev, entry, src }) + .then(() => core_js.export({ src, dest })) .then(() => { const elapsed = Date.now() - start; console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' @@ -28,3 +51,4 @@ if (cmd === 'build') { console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); }); } +//# sourceMappingURL=cli.js.map diff --git a/cli.js.map b/cli.js.map new file mode 100644 index 0000000..6923c3b --- /dev/null +++ b/cli.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.js","sources":["src/config.js","src/cli/index.js"],"sourcesContent":["import * as path from 'path';\nimport mkdirp from 'mkdirp';\nimport rimraf from 'rimraf';\n\nexport const dev = process.env.NODE_ENV !== 'production';\n\nexport const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates');\n\nexport const src = path.resolve(process.env.SAPPER_ROUTES || 'routes');\n\nexport const dest = path.resolve(process.env.SAPPER_DEST || '.sapper');\n\nif (dev) {\n\tmkdirp.sync(dest);\n\trimraf.sync(path.join(dest, '**/*'));\n}\n\nexport const entry = {\n\tclient: path.resolve(templates, '.main.rendered.js'),\n\tserver: path.resolve(dest, 'server-entry.js')\n};","import { build, export as exporter } from 'sapper/core.js';\nimport { dest, dev, entry, src } from '../config.js';\n\nconst cmd = process.argv[2];\nconst start = Date.now();\n\nif (cmd === 'build') {\n\tbuild({ dest, dev, entry, src })\n\t\t.then(() => {\n\t\t\tconst elapsed = Date.now() - start;\n\t\t\tconsole.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'\n\t\t})\n\t\t.catch(err => {\n\t\t\tconsole.error(err ? err.details || err.stack || err.message || err : 'Unknown error');\n\t\t});\n} else if (cmd === 'export') {\n\tconst start = Date.now();\n\n\tbuild({ dest, dev, entry, src })\n\t\t.then(() => exporter({ src, dest }))\n\t\t.then(() => {\n\t\t\tconst elapsed = Date.now() - start;\n\t\t\tconsole.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'\n\t\t})\n\t\t.catch(err => {\n\t\t\tconsole.error(err ? err.details || err.stack || err.message || err : 'Unknown error');\n\t\t});\n}\n"],"names":["path.resolve","path.join","build","exporter"],"mappings":";;;;;;;;;;AAIO,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;;AAEzD,AAAO,MAAM,SAAS,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW,CAAC,CAAC;;AAEnF,AAAO,MAAM,GAAG,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC;;AAEvE,AAAO,MAAM,IAAI,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC;;AAEvE,IAAI,GAAG,EAAE;CACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;CAClB,MAAM,CAAC,IAAI,CAACC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACrC;;AAED,AAAO,MAAM,KAAK,GAAG;CACpB,MAAM,EAAED,YAAY,CAAC,SAAS,EAAE,mBAAmB,CAAC;CACpD,MAAM,EAAEA,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC;CAC7C;;ACjBD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;;AAEzB,IAAI,GAAG,KAAK,OAAO,EAAE;CACpBE,aAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;GAC9B,IAAI,CAAC,MAAM;GACX,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;GACnC,OAAO,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;GACvC,CAAC;GACD,KAAK,CAAC,GAAG,IAAI;GACb,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,eAAe,CAAC,CAAC;GACtF,CAAC,CAAC;CACJ,MAAM,IAAI,GAAG,KAAK,QAAQ,EAAE;CAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;;CAEzBA,aAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;GAC9B,IAAI,CAAC,MAAMC,cAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;GACnC,IAAI,CAAC,MAAM;GACX,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;GACnC,OAAO,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;GAC3C,CAAC;GACD,KAAK,CAAC,GAAG,IAAI;GACb,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,eAAe,CAAC,CAAC;GACtF,CAAC,CAAC;CACJ"} \ No newline at end of file diff --git a/core.js.map b/core.js.map new file mode 100644 index 0000000..4a8d6ed --- /dev/null +++ b/core.js.map @@ -0,0 +1 @@ +{"version":3,"file":"core.js","sources":["src/core/utils/create_routes.js","src/core/route_manager.js","src/core/templates.js","src/core/utils/compilers.js","src/core/utils/create_app.js","src/core/generate_asset_cache.js","src/core/build.js","src/core/export.js"],"sourcesContent":["import * as path from 'path';\n\nexport default function create_routes(files) {\n\tconst routes = files\n\t\t.map(file => {\n\t\t\tif (/(^|\\/|\\\\)_/.test(file)) return;\n\n\t\t\tconst parts = file.replace(/\\.(html|js|mjs)$/, '').split('/'); // glob output is always posix-style\n\t\t\tif (parts[parts.length - 1] === 'index') parts.pop();\n\n\t\t\tconst id = (\n\t\t\t\tparts.join('_').replace(/[[\\]]/g, '$').replace(/^\\d/, '_$&').replace(/[^a-zA-Z0-9_$]/g, '_')\n\t\t\t ) || '_';\n\n\t\t\tconst dynamic = parts\n\t\t\t\t.filter(part => part[0] === '[')\n\t\t\t\t.map(part => part.slice(1, -1));\n\n\t\t\tlet pattern_string = '';\n\t\t\tlet i = parts.length;\n\t\t\tlet nested = true;\n\t\t\twhile (i--) {\n\t\t\t\tconst part = parts[i];\n\t\t\t\tconst dynamic = part[0] === '[';\n\n\t\t\t\tif (dynamic) {\n\t\t\t\t\tpattern_string = nested ? `(?:\\\\/([^/]+)${pattern_string})?` : `\\\\/([^/]+)${pattern_string}`;\n\t\t\t\t} else {\n\t\t\t\t\tnested = false;\n\t\t\t\t\tpattern_string = `\\\\/${part}${pattern_string}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst pattern = new RegExp(`^${pattern_string}\\\\/?$`);\n\n\t\t\tconst test = url => pattern.test(url);\n\n\t\t\tconst exec = url => {\n\t\t\t\tconst match = pattern.exec(url);\n\t\t\t\tif (!match) return;\n\n\t\t\t\tconst params = {};\n\t\t\t\tdynamic.forEach((param, i) => {\n\t\t\t\t\tparams[param] = match[i + 1];\n\t\t\t\t});\n\n\t\t\t\treturn params;\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\ttype: path.extname(file) === '.html' ? 'page' : 'route',\n\t\t\t\tfile,\n\t\t\t\tpattern,\n\t\t\t\ttest,\n\t\t\t\texec,\n\t\t\t\tparts,\n\t\t\t\tdynamic\n\t\t\t};\n\t\t})\n\t\t.filter(Boolean)\n\t\t.sort((a, b) => {\n\t\t\tlet same = true;\n\n\t\t\tfor (let i = 0; true; i += 1) {\n\t\t\t\tconst a_part = a.parts[i];\n\t\t\t\tconst b_part = b.parts[i];\n\n\t\t\t\tif (!a_part && !b_part) {\n\t\t\t\t\tif (same) throw new Error(`The ${a.file} and ${b.file} routes clash`);\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\tif (!a_part) return -1;\n\t\t\t\tif (!b_part) return 1;\n\n\t\t\t\tconst a_is_dynamic = a_part[0] === '[';\n\t\t\t\tconst b_is_dynamic = b_part[0] === '[';\n\n\t\t\t\tif (a_is_dynamic === b_is_dynamic) {\n\t\t\t\t\tif (!a_is_dynamic && a_part !== b_part) same = false;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\treturn a_is_dynamic ? 1 : -1;\n\t\t\t}\n\t\t});\n\n\treturn routes;\n}","import glob from 'glob';\nimport create_routes from './utils/create_routes.js';\n\nexport let routes;\n\nexport function update({ src }) {\n\troutes = create_routes(\n\t\tglob.sync('**/*.+(html|js|mjs)', { cwd: src })\n\t);\n\n\treturn routes;\n}","import * as fs from 'fs';\nimport glob from 'glob';\nimport chalk from 'chalk';\nimport framer from 'code-frame';\nimport { locate } from 'locate-character';\n\nlet templates;\n\nfunction error(e) {\n\tif (e.title) console.error(chalk.bold.red(e.title));\n\tif (e.body) console.error(chalk.red(e.body));\n\tif (e.url) console.error(chalk.cyan(e.url));\n\tif (e.frame) console.error(chalk.grey(e.frame));\n\n\tprocess.exit(1);\n}\n\nexport function create_templates() {\n\ttemplates = glob.sync('*.html', { cwd: 'templates' })\n\t\t.map(file => {\n\t\t\tconst template = fs.readFileSync(`templates/${file}`, 'utf-8');\n\t\t\tconst status = file.replace('.html', '').toLowerCase();\n\n\t\t\tif (!/^[0-9x]{3}$/.test(status)) {\n\t\t\t\terror({\n\t\t\t\t\ttitle: `templates/${file}`,\n\t\t\t\t\tbody: `Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html`\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst index = template.indexOf('%sapper.main%');\n\t\t\tif (index !== -1) {\n\t\t\t\t// TODO remove this in a future version\n\t\t\t\tconst { line, column } = locate(template, index, { offsetLine: 1 });\n\t\t\t\tconst frame = framer(template, line, column);\n\n\t\t\t\terror({\n\t\t\t\t\ttitle: `templates/${file}`,\n\t\t\t\t\tbody: ``;\n\n\t\t\t\t\t\tif (serialized) {\n\t\t\t\t\t\t\treturn `${main}`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn main;\n\t\t\t\t\t}),\n\t\t\t\t\thtml: promise.then(({ rendered }) => rendered.html),\n\t\t\t\t\thead: promise.then(({ rendered }) => `${rendered.head}`),\n\t\t\t\t\tstyles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `` : ''))\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst { html, head, css } = mod.render(data);\n\n\t\t\t\tconst page = templates.render(200, {\n\t\t\t\t\tscripts: ``,\n\t\t\t\t\thtml,\n\t\t\t\t\thead: `${head}`,\n\t\t\t\t\tstyles: (css && css.code ? `` : '')\n\t\t\t\t});\n\n\t\t\t\tres.end(page);\n\t\t\t}\n\t\t}\n\n\t\telse {\n\t\t\tconst method = req.method.toLowerCase();\n\t\t\t// 'delete' cannot be exported from a module because it is a keyword,\n\t\t\t// so check for 'del' instead\n\t\t\tconst method_export = method === 'delete' ? 'del' : method;\n\t\t\tconst handler = mod[method_export];\n\t\t\tif (handler) {\n\t\t\t\thandler(req, res, next);\n\t\t\t} else {\n\t\t\t\t// no matching handler for method — 404\n\t\t\t\tnext();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn function find_route(req, res, next) {\n\t\tconst url = req.pathname;\n\n\t\t// whatever happens, we're going to serve some HTML\n\t\tres.setHeader('Content-Type', 'text/html');\n\n\t\tresolved\n\t\t\t.then(() => {\n\t\t\t\tfor (const route of route_manager.routes) {\n\t\t\t\t\tif (route.test(url)) return handle_route(route, req, res, next, fn());\n\t\t\t\t}\n\n\t\t\t\t// no matching route — 404\n\t\t\t\tnext();\n\t\t\t})\n\t\t\t.catch(err => {\n\t\t\t\tres.statusCode = 500;\n\t\t\t\tres.end(templates.render(500, {\n\t\t\t\t\ttitle: (err && err.name) || 'Internal server error',\n\t\t\t\t\turl,\n\t\t\t\t\terror: escape_html(err && (err.details || err.message || err) || 'Unknown error'),\n\t\t\t\t\tstack: err && err.stack.split('\\n').slice(1).join('\\n')\n\t\t\t\t}));\n\t\t\t});\n\t};\n}\n\nfunction get_not_found_handler(fn) {\n\treturn function handle_not_found(req, res) {\n\t\tconst asset_cache = fn();\n\n\t\tres.statusCode = 404;\n\t\tres.end(templates.render(404, {\n\t\t\ttitle: 'Not found',\n\t\t\tstatus: 404,\n\t\t\tmethod: req.method,\n\t\t\tscripts: ``,\n\t\t\turl: req.url\n\t\t}));\n\t};\n}\n\nfunction compose_handlers(handlers) {\n\treturn (req, res, next) => {\n\t\tlet i = 0;\n\t\tfunction go() {\n\t\t\tconst handler = handlers[i];\n\n\t\t\tif (handler) {\n\t\t\t\thandler(req, res, () => {\n\t\t\t\t\ti += 1;\n\t\t\t\t\tgo();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnext();\n\t\t\t}\n\t\t}\n\n\t\tgo();\n\t};\n}\n\nfunction read_json(file) {\n\treturn JSON.parse(fs.readFileSync(file, 'utf-8'));\n}\n\nfunction try_serialize(data) {\n\ttry {\n\t\treturn serialize(data);\n\t} catch (err) {\n\t\treturn null;\n\t}\n}"],"names":["templates","path.resolve","path.join","fs.writeFileSync","generate_asset_cache","compilers","create_app","route_manager","fs.readFileSync"],"mappings":"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"} \ No newline at end of file diff --git a/mocha.opts b/mocha.opts index a1babb5..3b7d05f 100644 --- a/mocha.opts +++ b/mocha.opts @@ -1,4 +1,4 @@ ---require ts-node/register +--require source-map-support/register --recursive test/unit/**/*.js test/common/test.js \ No newline at end of file diff --git a/package.json b/package.json index 360d881..f6ddf51 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "npm-run-all": "^4.1.2", "rollup": "^0.53.0", "rollup-plugin-typescript": "^0.8.1", + "source-map-support": "^0.5.2", "style-loader": "^0.19.1", "svelte": "^1.49.1", "svelte-loader": "^2.3.2", diff --git a/rollup.config.js b/rollup.config.js index c8fae3b..f088d8a 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,7 +4,7 @@ import pkg from './package.json'; const external = [].concat( Object.keys(pkg.dependencies), Object.keys(process.binding('natives')), - 'sapper' + 'sapper/core.js' ); const paths = { @@ -18,10 +18,11 @@ export default [ output: { file: 'cli.js', format: 'cjs', - banner: '#!/usr/bin/env node' + banner: '#!/usr/bin/env node', + paths, + sourcemap: true }, external, - paths, plugins: [ typescript({ typescript: require('typescript') @@ -35,10 +36,11 @@ export default [ output: { file: 'core.js', format: 'cjs', - banner: '#!/usr/bin/env node' + banner: '#!/usr/bin/env node', + paths, + sourcemap: true }, external, - paths, plugins: [ typescript({ typescript: require('typescript') @@ -51,10 +53,11 @@ export default [ input: 'src/middleware/index.js', output: { file: 'middleware.js', - format: 'cjs' + format: 'cjs', + paths, + sourcemap: true }, external, - paths, plugins: [ typescript({ typescript: require('typescript') @@ -67,10 +70,11 @@ export default [ input: 'src/runtime/index.ts', output: { file: 'runtime.js', - format: 'es' + format: 'es', + paths, + sourcemap: true }, external, - paths, plugins: [ typescript({ typescript: require('typescript') @@ -83,10 +87,11 @@ export default [ input: 'src/webpack/index.js', output: { file: 'webpack/config.js', - format: 'cjs' + format: 'cjs', + paths, + sourcemap: true }, external, - paths, plugins: [ typescript({ typescript: require('typescript') diff --git a/runtime.js.map b/runtime.js.map new file mode 100644 index 0000000..50e4ce5 --- /dev/null +++ b/runtime.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runtime.js","sources":["src/runtime/utils.ts","src/runtime/index.ts"],"sourcesContent":["export function detach(node: Node) {\n\tnode.parentNode.removeChild(node);\n}\n\nexport function findAnchor(node: Node) {\n\twhile (node && node.nodeName.toUpperCase() !== 'A') node = node.parentNode; // SVG elements have a lowercase name\n\treturn node;\n}\n\nexport function which(event: MouseEvent) {\n\treturn event.which === null ? event.button : event.which;\n}\n\nexport function scroll_state() {\n\treturn {\n\t\tx: window.scrollX,\n\t\ty: window.scrollY\n\t};\n}","import { detach, findAnchor, scroll_state, which } from './utils';\nimport { Component, ComponentConstructor, Params, Query, Route, RouteData, ScrollPosition } from './interfaces';\n\nexport let component: Component;\nlet target: Node;\nlet routes: Route[];\n\nconst history = typeof window !== 'undefined' ? window.history : {\n\tpushState: (state: any, title: string, href: string) => {},\n\treplaceState: (state: any, title: string, href: string) => {},\n\tscrollRestoration: ''\n};\n\nconst scroll_history: Record = {};\nlet uid = 1;\nlet cid: number;\n\nif ('scrollRestoration' in history) {\n\thistory.scrollRestoration = 'manual';\n}\n\nfunction select_route(url: URL): { route: Route, data: RouteData } {\n\tif (url.origin !== window.location.origin) return null;\n\n\tfor (const route of routes) {\n\t\tconst match = route.pattern.exec(url.pathname);\n\t\tif (match) {\n\t\t\tconst params = route.params(match);\n\n\t\t\tconst query: Record = {};\n\t\t\tfor (const [key, value] of url.searchParams) query[key] = value || true;\n\n\t\t\treturn { route, data: { params, query } };\n\t\t}\n\t}\n}\n\nlet current_token: {};\n\nfunction render(Component: ComponentConstructor, data: any, scroll: ScrollPosition, token: {}) {\n\tif (current_token !== token) return;\n\n\tif (component) {\n\t\tcomponent.destroy();\n\t} else {\n\t\t// first load — remove SSR'd contents\n\t\tconst start = document.querySelector('#sapper-head-start');\n\t\tconst end = document.querySelector('#sapper-head-end');\n\n\t\tif (start && end) {\n\t\t\twhile (start.nextSibling !== end) detach(start.nextSibling);\n\t\t\tdetach(start);\n\t\t\tdetach(end);\n\t\t}\n\n\t\t// preload additional routes\n\t\troutes.reduce((promise: Promise, route) => promise.then(route.load), Promise.resolve());\n\t}\n\n\tcomponent = new Component({\n\t\ttarget,\n\t\tdata,\n\t\thydrate: !component\n\t});\n\n\tif (scroll) {\n\t\twindow.scrollTo(scroll.x, scroll.y);\n\t}\n}\n\nfunction prepare_route(Component: ComponentConstructor, data: RouteData) {\n\tif (!Component.preload) {\n\t\treturn { Component, data };\n\t}\n\n\tif (!component && window.__SAPPER__ && window.__SAPPER__.preloaded) {\n\t\treturn { Component, data: Object.assign(data, window.__SAPPER__.preloaded) };\n\t}\n\n\treturn Promise.resolve(Component.preload(data)).then(preloaded => {\n\t\tObject.assign(data, preloaded)\n\t\treturn { Component, data };\n\t});\n}\n\nfunction navigate(url: URL, id: number) {\n\tconst selected = select_route(url);\n\tif (selected) {\n\t\tif (id) {\n\t\t\t// popstate or initial navigation\n\t\t\tcid = id;\n\t\t} else {\n\t\t\t// clicked on a link. preserve scroll state\n\t\t\tscroll_history[cid] = scroll_state();\n\n\t\t\tid = cid = ++uid;\n\t\t\tscroll_history[cid] = { x: 0, y: 0 };\n\t\t}\n\n\t\tconst loaded = prefetching && prefetching.href === url.href ?\n\t\t\tprefetching.promise :\n\t\t\tselected.route.load().then(mod => prepare_route(mod.default, selected.data));\n\n\t\tprefetching = null;\n\n\t\tconst token = current_token = {};\n\n\t\tloaded.then(({ Component, data }) => {\n\t\t\trender(Component, data, scroll_history[id], token);\n\t\t});\n\n\t\tcid = id;\n\t\treturn true;\n\t}\n}\n\nfunction handle_click(event: MouseEvent) {\n\t// Adapted from https://github.com/visionmedia/page.js\n\t// MIT license https://github.com/visionmedia/page.js#license\n\tif (which(event) !== 1) return;\n\tif (event.metaKey || event.ctrlKey || event.shiftKey) return;\n\tif (event.defaultPrevented) return;\n\n\tconst a: HTMLAnchorElement | SVGAElement = findAnchor(event.target);\n\tif (!a) return;\n\n\t// check if link is inside an svg\n\t// in this case, both href and target are always inside an object\n\tconst svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString';\n\tconst href = String(svg ? (a).href.baseVal : a.href);\n\n\tif (href === window.location.href) {\n\t\tevent.preventDefault();\n\t\treturn;\n\t}\n\n\t// Ignore if tag has\n\t// 1. 'download' attribute\n\t// 2. rel='external' attribute\n\tif (a.hasAttribute('download') || a.getAttribute('rel') === 'external') return;\n\n\t// Ignore if has a target\n\tif (svg ? (a).target.baseVal : a.target) return;\n\n\tconst url = new URL(href);\n\n\t// Don't handle hash changes\n\tif (url.pathname === window.location.pathname && url.search === window.location.search) return;\n\n\tif (navigate(url, null)) {\n\t\tevent.preventDefault();\n\t\thistory.pushState({ id: cid }, '', url.href);\n\t}\n}\n\nfunction handle_popstate(event: PopStateEvent) {\n\tscroll_history[cid] = scroll_state();\n\n\tif (event.state) {\n\t\tnavigate(new URL(window.location.href), event.state.id);\n\t} else {\n\t\t// hashchange\n\t\tcid = ++uid;\n\t\thistory.replaceState({ id: cid }, '', window.location.href);\n\t}\n}\n\nlet prefetching: {\n\thref: string;\n\tpromise: Promise<{ Component: ComponentConstructor, data: any }>;\n} = null;\n\nexport function prefetch(href: string) {\n\tconst selected = select_route(new URL(href));\n\n\tif (selected) {\n\t\tprefetching = {\n\t\t\thref,\n\t\t\tpromise: selected.route.load().then(mod => prepare_route(mod.default, selected.data))\n\t\t};\n\t}\n}\n\nfunction handle_touchstart_mouseover(event: MouseEvent | TouchEvent) {\n\tconst a: HTMLAnchorElement = findAnchor(event.target);\n\tif (!a || a.rel !== 'prefetch') return;\n\n\tprefetch(a.href);\n}\n\nlet inited: boolean;\n\nexport function init(_target: Node, _routes: Route[]) {\n\ttarget = _target;\n\troutes = _routes;\n\n\tif (!inited) { // this check makes HMR possible\n\t\twindow.addEventListener('click', handle_click);\n\t\twindow.addEventListener('popstate', handle_popstate);\n\n\t\t// prefetch\n\t\twindow.addEventListener('touchstart', handle_touchstart_mouseover);\n\t\twindow.addEventListener('mouseover', handle_touchstart_mouseover);\n\n\t\tinited = true;\n\t}\n\n\tsetTimeout(() => {\n\t\tconst { hash, href } = window.location;\n\n\t\tconst deep_linked = hash && document.querySelector(hash);\n\t\tscroll_history[uid] = deep_linked ?\n\t\t\t{ x: 0, y: deep_linked.getBoundingClientRect().top } :\n\t\t\tscroll_state();\n\n\t\thistory.replaceState({ id: uid }, '', href);\n\t\tnavigate(new URL(window.location.href), uid);\n\t});\n}\n\nexport function goto(href: string, opts = { replaceState: false }) {\n\tif (navigate(new URL(href, window.location.href), null)) {\n\t\tif (history) history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href);\n\t} else {\n\t\twindow.location.href = href;\n\t}\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/cli/index.js b/src/cli/index.js index 64478c4..2ce467b 100755 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -1,10 +1,11 @@ import { build, export as exporter } from 'sapper/core.js'; +import { dest, dev, entry, src } from '../config.js'; const cmd = process.argv[2]; const start = Date.now(); if (cmd === 'build') { - build() + build({ dest, dev, entry, src }) .then(() => { const elapsed = Date.now() - start; console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' @@ -15,8 +16,8 @@ if (cmd === 'build') { } else if (cmd === 'export') { const start = Date.now(); - build() - .then(() => exporter()) + build({ dest, dev, entry, src }) + .then(() => exporter({ src, dest })) .then(() => { const elapsed = Date.now() - start; console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' diff --git a/src/core/build.js b/src/core/build.js index 3f18d0a..aaf6999 100644 --- a/src/core/build.js +++ b/src/core/build.js @@ -4,17 +4,16 @@ import * as fs from 'fs'; import * as path from 'path'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; -import { client, server } from './utils/compilers.js'; +import * as compilers from './utils/compilers.js'; import create_app from './utils/create_app.js'; import generate_asset_cache from './generate_asset_cache.js'; -import { dest } from '../config.js'; -export default () => { +export default function build({ dest, dev, entry, src }) { mkdirp.sync(dest); rimraf.sync(path.join(dest, '**/*')); // create main.js and server-routes.js - create_app(); + create_app({ dev, entry, src }); return new Promise((fulfil, reject) => { function handleErrors(err, stats) { @@ -29,19 +28,21 @@ export default () => { } } - client.run((err, clientStats) => { - handleErrors(err, clientStats); - const clientInfo = clientStats.toJson(); - fs.writeFileSync(path.join(dest, 'stats.client.json'), JSON.stringify(clientInfo, null, ' ')); + const { client, server } = compilers.get_compilers(); // TODO refactor - server.run((err, serverStats) => { - handleErrors(err, serverStats); - const serverInfo = serverStats.toJson(); - fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(serverInfo, null, ' ')); + client.run((err, client_stats) => { + handleErrors(err, client_stats); + const client_info = client_stats.toJson(); + fs.writeFileSync(path.join(dest, 'stats.client.json'), JSON.stringify(client_info, null, ' ')); - generate_asset_cache(clientInfo, serverInfo); + server.run((err, server_stats) => { + handleErrors(err, server_stats); + const server_info = server_stats.toJson(); + fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(server_info, null, ' ')); + + generate_asset_cache({ src, dest, dev, client_info, server_info }); fulfil(); }); }); }); -}; +} diff --git a/src/core/export.js b/src/core/export.js index b13ea45..7416c36 100644 --- a/src/core/export.js +++ b/src/core/export.js @@ -5,8 +5,7 @@ import cheerio from 'cheerio'; import fetch from 'node-fetch'; import URL from 'url-parse'; import generate_asset_cache from './generate_asset_cache.js'; -import { dest } from '../config.js'; -import middleware from '../middleware/index.js'; +// import middleware from '../middleware/index.js'; const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env; @@ -18,14 +17,16 @@ function read_json(file) { return JSON.parse(sander.readFileSync(file, { encoding: 'utf-8' })); } -export default function() { +export default function exporter({ src, dest }) { // TODO dest is a terrible name in this context // Prep output directory sander.rimrafSync(OUTPUT_DIR); - const { service_worker } = generate_asset_cache( - read_json(path.join(dest, 'stats.client.json')), - read_json(path.join(dest, 'stats.server.json')) - ); + const { service_worker } = generate_asset_cache({ + src, dest, + dev: false, + client_info: read_json(path.join(dest, 'stats.client.json')), + server_info: read_json(path.join(dest, 'stats.server.json')) + }); sander.copydirSync('assets').to(OUTPUT_DIR); sander.copydirSync(dest, 'client').to(OUTPUT_DIR, 'client'); @@ -62,7 +63,7 @@ export default function() { return fetch(url, opts); }; - app.use(middleware()); + app.use(require('./middleware')()); // TODO this is filthy const server = app.listen(PORT); const seen = new Set(); diff --git a/src/core/generate_asset_cache.js b/src/core/generate_asset_cache.js index 91ae425..05546e1 100644 --- a/src/core/generate_asset_cache.js +++ b/src/core/generate_asset_cache.js @@ -3,18 +3,19 @@ import * as path from 'path'; import glob from 'glob'; import * as templates from './templates.js'; import * as route_manager from './route_manager.js'; -import { dest, dev } from '../config.js'; function ensure_array(thing) { return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing } -export default function generate_asset_cache(clientInfo, serverInfo) { - const main_file = `/client/${ensure_array(clientInfo.assetsByChunkName.main)[0]}`; +export default function generate_asset_cache({ src, dest, dev, client_info, server_info }) { + templates.create_templates(); // TODO refactor this... - const chunk_files = clientInfo.assets.map(chunk => `/client/${chunk.name}`); + const main_file = `/client/${ensure_array(client_info.assetsByChunkName.main)[0]}`; - const service_worker = generate_service_worker(chunk_files); + const chunk_files = client_info.assets.map(chunk => `/client/${chunk.name}`); + + const service_worker = generate_service_worker({ chunk_files, src }); const index = generate_index(main_file); if (dev) { @@ -34,7 +35,7 @@ export default function generate_asset_cache(clientInfo, serverInfo) { }, {}), routes: route_manager.routes.reduce((lookup, route) => { - lookup[route.id] = `/client/${ensure_array(clientInfo.assetsByChunkName[route.id])[0]}`; + lookup[route.id] = `/client/${ensure_array(client_info.assetsByChunkName[route.id])[0]}`; return lookup; }, {}), @@ -43,16 +44,18 @@ export default function generate_asset_cache(clientInfo, serverInfo) { }, server: { - entry: path.resolve(dest, 'server', serverInfo.assetsByChunkName.main) + entry: path.resolve(dest, 'server', server_info.assetsByChunkName.main) }, service_worker }; } -function generate_service_worker(chunk_files) { +function generate_service_worker({ chunk_files, src }) { const assets = glob.sync('**', { cwd: 'assets', nodir: true }); + route_manager.update({ src }); // TODO refactor + const route_code = `[${ route_manager.routes .filter(route => route.type === 'page') diff --git a/src/core/index.js b/src/core/index.js index ced82f2..ee0513c 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -6,5 +6,6 @@ export { default as build } from './build.js'; export { default as export } from './export.js'; export { default as generate_asset_cache } from './generate_asset_cache.js'; export { default as create_app } from './utils/create_app.js'; +export { default as create_routes } from './utils/create_routes.js'; export { compilers, route_manager, templates }; \ No newline at end of file diff --git a/src/core/route_manager.js b/src/core/route_manager.js index 9efe5b9..3d559b4 100644 --- a/src/core/route_manager.js +++ b/src/core/route_manager.js @@ -1,32 +1,12 @@ import glob from 'glob'; import create_routes from './utils/create_routes.js'; -import { src, dev } from '../config.js'; - -const callbacks = []; - -export function onchange(fn) { - callbacks.push(fn); -} export let routes; -function update() { +export function update({ src }) { routes = create_routes( glob.sync('**/*.+(html|js|mjs)', { cwd: src }) ); - callbacks.forEach(fn => fn()); -} - -update(); - -if (dev) { - const watcher = require('chokidar').watch(`${src}/**/*.+(html|js|mjs)`, { - ignoreInitial: true, - persistent: false - }); - - watcher.on('add', update); - watcher.on('change', update); - watcher.on('unlink', update); -} + return routes; +} \ No newline at end of file diff --git a/src/core/templates.js b/src/core/templates.js index 216783c..c95a07e 100644 --- a/src/core/templates.js +++ b/src/core/templates.js @@ -3,7 +3,6 @@ import glob from 'glob'; import chalk from 'chalk'; import framer from 'code-frame'; import { locate } from 'locate-character'; -import { dev } from '../config.js'; let templates; @@ -16,7 +15,7 @@ function error(e) { process.exit(1); } -function create_templates() { +export function create_templates() { templates = glob.sync('*.html', { cwd: 'templates' }) .map(file => { const template = fs.readFileSync(`templates/${file}`, 'utf-8'); @@ -99,19 +98,6 @@ function create_templates() { .sort((a, b) => b.specificity - a.specificity); } -create_templates(); - -if (dev) { - const watcher = require('chokidar').watch('templates/**.html', { - ignoreInitial: true, - persistent: false - }); - - watcher.on('add', create_templates); - watcher.on('change', create_templates); - watcher.on('unlink', create_templates); -} - export function render(status, data) { const template = templates.find(template => template.test(status)); if (template) return template.render(data); diff --git a/src/core/utils/compilers.js b/src/core/utils/compilers.js index 3def12e..4424d45 100644 --- a/src/core/utils/compilers.js +++ b/src/core/utils/compilers.js @@ -3,10 +3,25 @@ import relative from 'require-relative'; const webpack = relative('webpack', process.cwd()); -export const client = webpack( - require(path.resolve('webpack.client.config.js')) -); +export let client; +export let server; -export const server = webpack( - require(path.resolve('webpack.server.config.js')) -); \ No newline at end of file +export function get_compilers() { + return { + client: webpack( + require(path.resolve('webpack.client.config.js')) + ), + + server: webpack( + require(path.resolve('webpack.server.config.js')) + ) + }; +} + +// export const client = webpack( +// require(path.resolve('webpack.client.config.js')) +// ); + +// export const server = webpack( +// require(path.resolve('webpack.server.config.js')) +// ); \ No newline at end of file diff --git a/src/core/utils/create_app.js b/src/core/utils/create_app.js index 6fcb64e..4046482 100644 --- a/src/core/utils/create_app.js +++ b/src/core/utils/create_app.js @@ -1,13 +1,15 @@ import * as fs from 'fs'; import * as path from 'path'; import * as route_manager from '../route_manager.js'; -import { src, entry, dev } from '../../config.js'; +import * as templates from '../templates.js'; function posixify(file) { return file.replace(/[/\\]/g, '/'); } -function create_app() { +function create_app({ src, dev, entry }) { + // const { routes } = route_manager; + route_manager.update({ src }); const { routes } = route_manager; function create_client_main() { @@ -66,17 +68,31 @@ function create_app() { create_server_routes(); } -if (dev) { - route_manager.onchange(create_app); +export function start_watching({ src }) { + const chokidar = require('chokidar'); - const watcher = require('chokidar').watch(`templates/main.js`, { - ignoreInitial: true, - persistent: false + const watch = (glob, callback) => { + const watcher = chokidar.watch(glob, { + ignoreInitial: true, + persistent: false + }); + + watcher.on('add', callback); + watcher.on('change', callback); + watcher.on('unlink', callback); + }; + + watch('templates/main.js', create_app); + + watch('routes/**/*.+(html|js|mjs)', () => { + route_manager.update({ src }); + create_app(); }); - watcher.on('add', create_app); - watcher.on('change', create_app); - watcher.on('unlink', create_app); + watch('templates/**.html', () => { + templates.create_templates(); + // TODO reload current page? + }); } export default create_app; diff --git a/src/core/utils/create_routes.js b/src/core/utils/create_routes.js index 97b6d09..bf8d351 100644 --- a/src/core/utils/create_routes.js +++ b/src/core/utils/create_routes.js @@ -1,6 +1,6 @@ import * as path from 'path'; -export default function create_matchers(files) { +export default function create_routes(files) { const routes = files .map(file => { if (/(^|\/|\\)_/.test(file)) return; diff --git a/src/middleware/index.js b/src/middleware/index.js index 89bb113..525f483 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -4,10 +4,10 @@ import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; import { route_manager, templates, create_app, compilers, generate_asset_cache } from 'sapper/core.js'; import create_watcher from './create_watcher.js'; -import { dest, dev } from '../config.js'; +import { dest, dev, entry, src } from '../config.js'; function connect_dev() { - create_app(); + create_app({ dev, entry, src }); const watcher = create_watcher(); @@ -64,10 +64,12 @@ function connect_dev() { } function connect_prod() { - const asset_cache = generate_asset_cache( - read_json(path.join(dest, 'stats.client.json')), - read_json(path.join(dest, 'stats.server.json')) - ); + const asset_cache = generate_asset_cache({ + src, dest, + dev: false, + client_info: read_json(path.join(dest, 'stats.client.json')), + server_info: read_json(path.join(dest, 'stats.server.json')) + }); const middleware = compose_handlers([ set_req_pathname, diff --git a/test/common/test.js b/test/common/test.js index efe7216..db90ff8 100644 --- a/test/common/test.js +++ b/test/common/test.js @@ -1,13 +1,5 @@ -import * as path from 'path'; -import * as assert from 'assert'; - -// import express from 'express'; -// import Nightmare from 'nightmare'; -// import serve from 'serve-static'; -// import walkSync from 'walk-sync'; -// import fetch from 'node-fetch'; - -// TODO reintegrate these as imports +const path = require('path'); +const assert = require('assert'); const Nightmare = require('nightmare'); const express = require('express'); const serve = require('serve-static'); @@ -94,8 +86,10 @@ function run(env) { } return exec_promise.then(() => { - const resolved = require.resolve('../..'); + const resolved = require.resolve('../../middleware.js'); delete require.cache[resolved]; + delete require.cache[require.resolve('../../core.js')]; // TODO remove this + sapper = require(resolved); return require('get-port')(); diff --git a/test/unit/create_routes.test.js b/test/unit/create_routes.test.js index 8c2b291..2ece078 100644 --- a/test/unit/create_routes.test.js +++ b/test/unit/create_routes.test.js @@ -1,6 +1,5 @@ -import * as assert from 'assert'; - -import create_routes from '../../src/core/utils/create_routes.js'; +const assert = require('assert'); +const { create_routes } = require('../../core.js'); describe('create_routes', () => { it('sorts routes correctly', () => { diff --git a/webpack/config.js b/webpack/config.js index 0b51e8e..be6bfba 100644 --- a/webpack/config.js +++ b/webpack/config.js @@ -68,3 +68,4 @@ var index = { }; module.exports = index; +//# sourceMappingURL=config.js.map diff --git a/webpack/config.js.map b/webpack/config.js.map new file mode 100644 index 0000000..1be5aa7 --- /dev/null +++ b/webpack/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sources":["../src/config.js","../src/webpack/index.js"],"sourcesContent":["import * as path from 'path';\nimport mkdirp from 'mkdirp';\nimport rimraf from 'rimraf';\n\nexport const dev = process.env.NODE_ENV !== 'production';\n\nexport const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates');\n\nexport const src = path.resolve(process.env.SAPPER_ROUTES || 'routes');\n\nexport const dest = path.resolve(process.env.SAPPER_DEST || '.sapper');\n\nif (dev) {\n\tmkdirp.sync(dest);\n\trimraf.sync(path.join(dest, '**/*'));\n}\n\nexport const entry = {\n\tclient: path.resolve(templates, '.main.rendered.js'),\n\tserver: path.resolve(dest, 'server-entry.js')\n};","import { dest, dev, entry } from '../config.js';\n\nexport default {\n\tdev,\n\n\tclient: {\n\t\tentry: () => {\n\t\t\treturn {\n\t\t\t\tmain: [\n\t\t\t\t\tentry.client,\n\t\t\t\t\t// workaround for https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456\n\t\t\t\t\t'style-loader/lib/addStyles',\n\t\t\t\t\t'css-loader/lib/css-base'\n\t\t\t\t]\n\t\t\t};\n\t\t},\n\n\t\toutput: () => {\n\t\t\treturn {\n\t\t\t\tpath: `${dest}/client`,\n\t\t\t\tfilename: '[name].[hash].js',\n\t\t\t\tchunkFilename: '[name].[id].[hash].js',\n\t\t\t\tpublicPath: '/client/'\n\t\t\t};\n\t\t}\n\t},\n\n\tserver: {\n\t\tentry: () => {\n\t\t\treturn {\n\t\t\t\tmain: entry.server\n\t\t\t};\n\t\t},\n\n\t\toutput: () => {\n\t\t\treturn {\n\t\t\t\tpath: `${dest}/server`,\n\t\t\t\tfilename: '[name].[hash].js',\n\t\t\t\tchunkFilename: '[name].[id].[hash].js',\n\t\t\t\tlibraryTarget: 'commonjs2'\n\t\t\t};\n\t\t}\n\t}\n};\n"],"names":["path.resolve","path.join"],"mappings":";;;;;;;;AAIO,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;;AAEzD,AAAO,MAAM,SAAS,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW,CAAC,CAAC;;AAEnF,AAAO,MAAM,GAAG,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC;;AAEvE,AAAO,MAAM,IAAI,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC;;AAEvE,IAAI,GAAG,EAAE;CACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;CAClB,MAAM,CAAC,IAAI,CAACC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACrC;;AAED,AAAO,MAAM,KAAK,GAAG;CACpB,MAAM,EAAED,YAAY,CAAC,SAAS,EAAE,mBAAmB,CAAC;CACpD,MAAM,EAAEA,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC;CAC7C;;AClBD,YAAe;CACd,GAAG;;CAEH,MAAM,EAAE;EACP,KAAK,EAAE,MAAM;GACZ,OAAO;IACN,IAAI,EAAE;KACL,KAAK,CAAC,MAAM;;KAEZ,4BAA4B;KAC5B,yBAAyB;KACzB;IACD,CAAC;GACF;;EAED,MAAM,EAAE,MAAM;GACb,OAAO;IACN,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;IACtB,QAAQ,EAAE,kBAAkB;IAC5B,aAAa,EAAE,uBAAuB;IACtC,UAAU,EAAE,UAAU;IACtB,CAAC;GACF;EACD;;CAED,MAAM,EAAE;EACP,KAAK,EAAE,MAAM;GACZ,OAAO;IACN,IAAI,EAAE,KAAK,CAAC,MAAM;IAClB,CAAC;GACF;;EAED,MAAM,EAAE,MAAM;GACb,OAAO;IACN,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;IACtB,QAAQ,EAAE,kBAAkB;IAC5B,aAAa,EAAE,uBAAuB;IACtC,aAAa,EAAE,WAAW;IAC1B,CAAC;GACF;EACD;CACD,CAAC;;;;"} \ No newline at end of file From 03ce2ea998a2ee955ef41098c59cec67aff891ff Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 15:04:22 -0500 Subject: [PATCH 4/9] tidy up a bit --- .gitignore | 7 +- cli.js | 54 ----- cli.js.map | 1 - core.js.map | 1 - middleware.js | 361 ------------------------------- middleware.js.map | 1 - src/config.js | 9 - src/core/generate_asset_cache.js | 6 +- src/core/utils/compilers.js | 17 +- src/core/utils/create_app.js | 4 +- src/middleware/index.js | 5 + webpack/config.js | 71 ------ webpack/config.js.map | 1 - 13 files changed, 19 insertions(+), 519 deletions(-) delete mode 100644 cli.js delete mode 100644 cli.js.map delete mode 100644 core.js.map delete mode 100644 middleware.js delete mode 100644 middleware.js.map delete mode 100644 webpack/config.js delete mode 100644 webpack/config.js.map diff --git a/.gitignore b/.gitignore index 13773db..345e41f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,10 @@ test/app/.sapper runtime.js yarn.lock cli.js +cli.js.map middleware.js -core.js \ No newline at end of file +middleware.js.map +core.js +core.js.map +webpack/config.js +webpack/config.js.map \ No newline at end of file diff --git a/cli.js b/cli.js deleted file mode 100644 index 40ec17b..0000000 --- a/cli.js +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var core_js = require('./core.js'); -var path = require('path'); -var mkdirp = _interopDefault(require('mkdirp')); -var rimraf = _interopDefault(require('rimraf')); - -const dev = process.env.NODE_ENV !== 'production'; - -const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); - -const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); - -const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); - -if (dev) { - mkdirp.sync(dest); - rimraf.sync(path.join(dest, '**/*')); -} - -const entry = { - client: path.resolve(templates, '.main.rendered.js'), - server: path.resolve(dest, 'server-entry.js') -}; - -const cmd = process.argv[2]; -const start = Date.now(); - -if (cmd === 'build') { - core_js.build({ dest, dev, entry, src }) - .then(() => { - const elapsed = Date.now() - start; - console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' - }) - .catch(err => { - console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); - }); -} else if (cmd === 'export') { - const start = Date.now(); - - core_js.build({ dest, dev, entry, src }) - .then(() => core_js.export({ src, dest })) - .then(() => { - const elapsed = Date.now() - start; - console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds' - }) - .catch(err => { - console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); - }); -} -//# sourceMappingURL=cli.js.map diff --git a/cli.js.map b/cli.js.map deleted file mode 100644 index 6923c3b..0000000 --- a/cli.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"cli.js","sources":["src/config.js","src/cli/index.js"],"sourcesContent":["import * as path from 'path';\nimport mkdirp from 'mkdirp';\nimport rimraf from 'rimraf';\n\nexport const dev = process.env.NODE_ENV !== 'production';\n\nexport const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates');\n\nexport const src = path.resolve(process.env.SAPPER_ROUTES || 'routes');\n\nexport const dest = path.resolve(process.env.SAPPER_DEST || '.sapper');\n\nif (dev) {\n\tmkdirp.sync(dest);\n\trimraf.sync(path.join(dest, '**/*'));\n}\n\nexport const entry = {\n\tclient: path.resolve(templates, '.main.rendered.js'),\n\tserver: path.resolve(dest, 'server-entry.js')\n};","import { build, export as exporter } from 'sapper/core.js';\nimport { dest, dev, entry, src } from '../config.js';\n\nconst cmd = process.argv[2];\nconst start = Date.now();\n\nif (cmd === 'build') {\n\tbuild({ dest, dev, entry, src })\n\t\t.then(() => {\n\t\t\tconst elapsed = Date.now() - start;\n\t\t\tconsole.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'\n\t\t})\n\t\t.catch(err => {\n\t\t\tconsole.error(err ? err.details || err.stack || err.message || err : 'Unknown error');\n\t\t});\n} else if (cmd === 'export') {\n\tconst start = Date.now();\n\n\tbuild({ dest, dev, entry, src })\n\t\t.then(() => exporter({ src, dest }))\n\t\t.then(() => {\n\t\t\tconst elapsed = Date.now() - start;\n\t\t\tconsole.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'\n\t\t})\n\t\t.catch(err => {\n\t\t\tconsole.error(err ? err.details || err.stack || err.message || err : 'Unknown error');\n\t\t});\n}\n"],"names":["path.resolve","path.join","build","exporter"],"mappings":";;;;;;;;;;AAIO,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;;AAEzD,AAAO,MAAM,SAAS,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW,CAAC,CAAC;;AAEnF,AAAO,MAAM,GAAG,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC;;AAEvE,AAAO,MAAM,IAAI,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC;;AAEvE,IAAI,GAAG,EAAE;CACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;CAClB,MAAM,CAAC,IAAI,CAACC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACrC;;AAED,AAAO,MAAM,KAAK,GAAG;CACpB,MAAM,EAAED,YAAY,CAAC,SAAS,EAAE,mBAAmB,CAAC;CACpD,MAAM,EAAEA,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC;CAC7C;;ACjBD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;;AAEzB,IAAI,GAAG,KAAK,OAAO,EAAE;CACpBE,aAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;GAC9B,IAAI,CAAC,MAAM;GACX,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;GACnC,OAAO,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;GACvC,CAAC;GACD,KAAK,CAAC,GAAG,IAAI;GACb,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,eAAe,CAAC,CAAC;GACtF,CAAC,CAAC;CACJ,MAAM,IAAI,GAAG,KAAK,QAAQ,EAAE;CAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;;CAEzBA,aAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;GAC9B,IAAI,CAAC,MAAMC,cAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;GACnC,IAAI,CAAC,MAAM;GACX,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;GACnC,OAAO,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;GAC3C,CAAC;GACD,KAAK,CAAC,GAAG,IAAI;GACb,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,eAAe,CAAC,CAAC;GACtF,CAAC,CAAC;CACJ"} \ No newline at end of file diff --git a/core.js.map b/core.js.map deleted file mode 100644 index 4a8d6ed..0000000 --- a/core.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"core.js","sources":["src/core/utils/create_routes.js","src/core/route_manager.js","src/core/templates.js","src/core/utils/compilers.js","src/core/utils/create_app.js","src/core/generate_asset_cache.js","src/core/build.js","src/core/export.js"],"sourcesContent":["import * as path from 'path';\n\nexport default function create_routes(files) {\n\tconst routes = files\n\t\t.map(file => {\n\t\t\tif (/(^|\\/|\\\\)_/.test(file)) return;\n\n\t\t\tconst parts = file.replace(/\\.(html|js|mjs)$/, '').split('/'); // glob output is always posix-style\n\t\t\tif (parts[parts.length - 1] === 'index') parts.pop();\n\n\t\t\tconst id = (\n\t\t\t\tparts.join('_').replace(/[[\\]]/g, '$').replace(/^\\d/, '_$&').replace(/[^a-zA-Z0-9_$]/g, '_')\n\t\t\t ) || '_';\n\n\t\t\tconst dynamic = parts\n\t\t\t\t.filter(part => part[0] === '[')\n\t\t\t\t.map(part => part.slice(1, -1));\n\n\t\t\tlet pattern_string = '';\n\t\t\tlet i = parts.length;\n\t\t\tlet nested = true;\n\t\t\twhile (i--) {\n\t\t\t\tconst part = parts[i];\n\t\t\t\tconst dynamic = part[0] === '[';\n\n\t\t\t\tif (dynamic) {\n\t\t\t\t\tpattern_string = nested ? `(?:\\\\/([^/]+)${pattern_string})?` : `\\\\/([^/]+)${pattern_string}`;\n\t\t\t\t} else {\n\t\t\t\t\tnested = false;\n\t\t\t\t\tpattern_string = `\\\\/${part}${pattern_string}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst pattern = new RegExp(`^${pattern_string}\\\\/?$`);\n\n\t\t\tconst test = url => pattern.test(url);\n\n\t\t\tconst exec = url => {\n\t\t\t\tconst match = pattern.exec(url);\n\t\t\t\tif (!match) return;\n\n\t\t\t\tconst params = {};\n\t\t\t\tdynamic.forEach((param, i) => {\n\t\t\t\t\tparams[param] = match[i + 1];\n\t\t\t\t});\n\n\t\t\t\treturn params;\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\ttype: path.extname(file) === '.html' ? 'page' : 'route',\n\t\t\t\tfile,\n\t\t\t\tpattern,\n\t\t\t\ttest,\n\t\t\t\texec,\n\t\t\t\tparts,\n\t\t\t\tdynamic\n\t\t\t};\n\t\t})\n\t\t.filter(Boolean)\n\t\t.sort((a, b) => {\n\t\t\tlet same = true;\n\n\t\t\tfor (let i = 0; true; i += 1) {\n\t\t\t\tconst a_part = a.parts[i];\n\t\t\t\tconst b_part = b.parts[i];\n\n\t\t\t\tif (!a_part && !b_part) {\n\t\t\t\t\tif (same) throw new Error(`The ${a.file} and ${b.file} routes clash`);\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\tif (!a_part) return -1;\n\t\t\t\tif (!b_part) return 1;\n\n\t\t\t\tconst a_is_dynamic = a_part[0] === '[';\n\t\t\t\tconst b_is_dynamic = b_part[0] === '[';\n\n\t\t\t\tif (a_is_dynamic === b_is_dynamic) {\n\t\t\t\t\tif (!a_is_dynamic && a_part !== b_part) same = false;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\treturn a_is_dynamic ? 1 : -1;\n\t\t\t}\n\t\t});\n\n\treturn routes;\n}","import glob from 'glob';\nimport create_routes from './utils/create_routes.js';\n\nexport let routes;\n\nexport function update({ src }) {\n\troutes = create_routes(\n\t\tglob.sync('**/*.+(html|js|mjs)', { cwd: src })\n\t);\n\n\treturn routes;\n}","import * as fs from 'fs';\nimport glob from 'glob';\nimport chalk from 'chalk';\nimport framer from 'code-frame';\nimport { locate } from 'locate-character';\n\nlet templates;\n\nfunction error(e) {\n\tif (e.title) console.error(chalk.bold.red(e.title));\n\tif (e.body) console.error(chalk.red(e.body));\n\tif (e.url) console.error(chalk.cyan(e.url));\n\tif (e.frame) console.error(chalk.grey(e.frame));\n\n\tprocess.exit(1);\n}\n\nexport function create_templates() {\n\ttemplates = glob.sync('*.html', { cwd: 'templates' })\n\t\t.map(file => {\n\t\t\tconst template = fs.readFileSync(`templates/${file}`, 'utf-8');\n\t\t\tconst status = file.replace('.html', '').toLowerCase();\n\n\t\t\tif (!/^[0-9x]{3}$/.test(status)) {\n\t\t\t\terror({\n\t\t\t\t\ttitle: `templates/${file}`,\n\t\t\t\t\tbody: `Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html`\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst index = template.indexOf('%sapper.main%');\n\t\t\tif (index !== -1) {\n\t\t\t\t// TODO remove this in a future version\n\t\t\t\tconst { line, column } = locate(template, index, { offsetLine: 1 });\n\t\t\t\tconst frame = framer(template, line, column);\n\n\t\t\t\terror({\n\t\t\t\t\ttitle: `templates/${file}`,\n\t\t\t\t\tbody: ``; - - if (serialized) { - return `${main}`; - } - - return main; - }), - html: promise.then(({ rendered }) => rendered.html), - head: promise.then(({ rendered }) => `${rendered.head}`), - styles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `` : '')) - }); - } else { - const { html, head, css } = mod.render(data); - - const page = core_js.templates.render(200, { - scripts: ``, - html, - head: `${head}`, - styles: (css && css.code ? `` : '') - }); - - res.end(page); - } - } - - else { - const method = req.method.toLowerCase(); - // 'delete' cannot be exported from a module because it is a keyword, - // so check for 'del' instead - const method_export = method === 'delete' ? 'del' : method; - const handler = mod[method_export]; - if (handler) { - handler(req, res, next); - } else { - // no matching handler for method — 404 - next(); - } - } - } - - return function find_route(req, res, next) { - const url = req.pathname; - - // whatever happens, we're going to serve some HTML - res.setHeader('Content-Type', 'text/html'); - - resolved - .then(() => { - for (const route of core_js.route_manager.routes) { - if (route.test(url)) return handle_route(route, req, res, next, fn()); - } - - // no matching route — 404 - next(); - }) - .catch(err => { - res.statusCode = 500; - res.end(core_js.templates.render(500, { - title: (err && err.name) || 'Internal server error', - url, - error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), - stack: err && err.stack.split('\n').slice(1).join('\n') - })); - }); - }; -} - -function get_not_found_handler(fn) { - return function handle_not_found(req, res) { - const asset_cache = fn(); - - res.statusCode = 404; - res.end(core_js.templates.render(404, { - title: 'Not found', - status: 404, - method: req.method, - scripts: ``, - url: req.url - })); - }; -} - -function compose_handlers(handlers) { - return (req, res, next) => { - let i = 0; - function go() { - const handler = handlers[i]; - - if (handler) { - handler(req, res, () => { - i += 1; - go(); - }); - } else { - next(); - } - } - - go(); - }; -} - -function read_json(file) { - return JSON.parse(fs.readFileSync(file, 'utf-8')); -} - -function try_serialize(data) { - try { - return serialize(data); - } catch (err) { - return null; - } -} - -module.exports = index; -//# sourceMappingURL=middleware.js.map diff --git a/middleware.js.map b/middleware.js.map deleted file mode 100644 index 883ece4..0000000 --- a/middleware.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"middleware.js","sources":["src/config.js","src/middleware/create_watcher.js","src/middleware/index.js"],"sourcesContent":["import * as path from 'path';\nimport mkdirp from 'mkdirp';\nimport rimraf from 'rimraf';\n\nexport const dev = process.env.NODE_ENV !== 'production';\n\nexport const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates');\n\nexport const src = path.resolve(process.env.SAPPER_ROUTES || 'routes');\n\nexport const dest = path.resolve(process.env.SAPPER_DEST || '.sapper');\n\nif (dev) {\n\tmkdirp.sync(dest);\n\trimraf.sync(path.join(dest, '**/*'));\n}\n\nexport const entry = {\n\tclient: path.resolve(templates, '.main.rendered.js'),\n\tserver: path.resolve(dest, 'server-entry.js')\n};","import * as fs from 'fs';\nimport * as path from 'path';\nimport chalk from 'chalk';\nimport { compilers, generate_asset_cache } from 'sapper/core.js';\nimport { dest } from '../config.js';\n\nfunction deferred() {\n\tconst d = {};\n\n\td.promise = new Promise((fulfil, reject) => {\n\t\td.fulfil = fulfil;\n\t\td.reject = reject;\n\t});\n\n\treturn d;\n}\n\nexport default function create_watcher() {\n\tconst deferreds = {\n\t\tclient: deferred(),\n\t\tserver: deferred()\n\t};\n\n\tconst invalidate = () => Promise.all([\n\t\tdeferreds.client.promise,\n\t\tdeferreds.server.promise\n\t]).then(([client_stats, server_stats]) => {\n\t\tconst client_info = client_stats.toJson();\n\t\tfs.writeFileSync(path.join(dest, 'stats.client.json'), JSON.stringify(client_info, null, ' '));\n\n\t\tconst server_info = server_stats.toJson();\n\t\tfs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(server_info, null, ' '));\n\n\t\treturn generate_asset_cache(\n\t\t\tclient_stats.toJson(),\n\t\t\tserver_stats.toJson()\n\t\t);\n\t});\n\n\tfunction watch_compiler(type) {\n\t\tconst compiler = compilers[type];\n\n\t\tcompiler.plugin('invalid', filename => {\n\t\t\tconsole.log(chalk.cyan(`${type} bundle invalidated, file changed: ${chalk.bold(filename)}`));\n\t\t\tdeferreds[type] = deferred();\n\t\t\twatcher.ready = invalidate();\n\t\t});\n\n\t\tcompiler.plugin('failed', err => {\n\t\t\tdeferreds[type].reject(err);\n\t\t});\n\n\t\treturn compiler.watch({}, (err, stats) => {\n\t\t\tif (stats.hasErrors()) {\n\t\t\t\tdeferreds[type].reject(stats.toJson().errors[0]);\n\t\t\t} else {\n\t\t\t\tdeferreds[type].fulfil(stats);\n\t\t\t}\n\t\t});\n\t}\n\n\tconst watcher = {\n\t\tready: invalidate(),\n\t\tclient: watch_compiler('client'),\n\t\tserver: watch_compiler('server'),\n\n\t\tclose: () => {\n\t\t\twatcher.client.close();\n\t\t\twatcher.server.close();\n\t\t}\n\t};\n\n\treturn watcher;\n}","import * as fs from 'fs';\nimport * as path from 'path';\nimport serialize from 'serialize-javascript';\nimport escape_html from 'escape-html';\nimport { route_manager, templates, create_app, compilers, generate_asset_cache } from 'sapper/core.js';\nimport create_watcher from './create_watcher.js';\nimport { dest, dev, entry, src } from '../config.js';\n\nfunction connect_dev() {\n\tcreate_app({ dev, entry, src });\n\n\tconst watcher = create_watcher();\n\n\tlet asset_cache;\n\n\tconst middleware = compose_handlers([\n\t\trequire('webpack-hot-middleware')(compilers.client, {\n\t\t\treload: true,\n\t\t\tpath: '/__webpack_hmr',\n\t\t\theartbeat: 10 * 1000\n\t\t}),\n\n\t\t(req, res, next) => {\n\t\t\twatcher.ready.then(cache => {\n\t\t\t\tasset_cache = cache;\n\t\t\t\tnext();\n\t\t\t});\n\t\t},\n\n\t\tset_req_pathname,\n\n\t\tget_asset_handler({\n\t\t\tfilter: pathname => pathname === '/index.html',\n\t\t\ttype: 'text/html',\n\t\t\tcache: 'max-age=600',\n\t\t\tfn: () => asset_cache.client.index\n\t\t}),\n\n\t\tget_asset_handler({\n\t\t\tfilter: pathname => pathname === '/service-worker.js',\n\t\t\ttype: 'application/javascript',\n\t\t\tcache: 'max-age=600',\n\t\t\tfn: () => asset_cache.client.service_worker\n\t\t}),\n\n\t\tget_asset_handler({\n\t\t\tfilter: pathname => pathname.startsWith('/client/'),\n\t\t\ttype: 'application/javascript',\n\t\t\tcache: 'max-age=31536000',\n\t\t\tfn: pathname => asset_cache.client.chunks[pathname]\n\t\t}),\n\n\t\tget_route_handler(() => asset_cache),\n\n\t\tget_not_found_handler(() => asset_cache)\n\t]);\n\n\tmiddleware.close = () => {\n\t\twatcher.close();\n\t\t// TODO shut down chokidar\n\t};\n\n\treturn middleware;\n}\n\nfunction connect_prod() {\n\tconst asset_cache = generate_asset_cache({\n\t\tsrc, dest,\n\t\tdev: false,\n\t\tclient_info: read_json(path.join(dest, 'stats.client.json')),\n\t\tserver_info: read_json(path.join(dest, 'stats.server.json'))\n\t});\n\n\tconst middleware = compose_handlers([\n\t\tset_req_pathname,\n\n\t\tget_asset_handler({\n\t\t\tfilter: pathname => pathname === '/index.html',\n\t\t\ttype: 'text/html',\n\t\t\tcache: 'max-age=600',\n\t\t\tfn: () => asset_cache.client.index\n\t\t}),\n\n\t\tget_asset_handler({\n\t\t\tfilter: pathname => pathname === '/service-worker.js',\n\t\t\ttype: 'application/javascript',\n\t\t\tcache: 'max-age=600',\n\t\t\tfn: () => asset_cache.client.service_worker\n\t\t}),\n\n\t\tget_asset_handler({\n\t\t\tfilter: pathname => pathname.startsWith('/client/'),\n\t\t\ttype: 'application/javascript',\n\t\t\tcache: 'max-age=31536000',\n\t\t\tfn: pathname => asset_cache.client.chunks[pathname]\n\t\t}),\n\n\t\tget_route_handler(() => asset_cache),\n\n\t\tget_not_found_handler(() => asset_cache)\n\t]);\n\n\t// here for API consistency between dev, and prod, but\n\t// doesn't actually need to do anything\n\tmiddleware.close = () => {};\n\n\treturn middleware;\n}\n\nexport default dev ? connect_dev : connect_prod;\n\nfunction set_req_pathname(req, res, next) {\n\treq.pathname = req.url.replace(/\\?.+/, '');\n\tnext();\n}\n\nfunction get_asset_handler(opts) {\n\treturn (req, res, next) => {\n\t\tif (!opts.filter(req.pathname)) return next();\n\n\t\tres.setHeader('Content-Type', opts.type);\n\t\tres.setHeader('Cache-Control', opts.cache);\n\n\t\tres.end(opts.fn(req.pathname));\n\t};\n}\n\nconst resolved = Promise.resolve();\n\nfunction get_route_handler(fn) {\n\tfunction handle_route(route, req, res, next, { client, server }) {\n\t\treq.params = route.exec(req.pathname);\n\n\t\tconst mod = require(server.entry)[route.id];\n\n\t\tif (route.type === 'page') {\n\t\t\t// preload main.js and current route\n\t\t\t// TODO detect other stuff we can preload? images, CSS, fonts?\n\t\t\tres.setHeader('Link', `<${client.main_file}>;rel=\"preload\";as=\"script\", <${client.routes[route.id]}>;rel=\"preload\";as=\"script\"`);\n\n\t\t\tconst data = { params: req.params, query: req.query };\n\n\t\t\tif (mod.preload) {\n\t\t\t\tconst promise = Promise.resolve(mod.preload(req)).then(preloaded => {\n\t\t\t\t\tconst serialized = try_serialize(preloaded);\n\t\t\t\t\tObject.assign(data, preloaded);\n\n\t\t\t\t\treturn { rendered: mod.render(data), serialized };\n\t\t\t\t});\n\n\t\t\t\treturn templates.stream(res, 200, {\n\t\t\t\t\tscripts: promise.then(({ serialized }) => {\n\t\t\t\t\t\tconst main = ``;\n\n\t\t\t\t\t\tif (serialized) {\n\t\t\t\t\t\t\treturn `${main}`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn main;\n\t\t\t\t\t}),\n\t\t\t\t\thtml: promise.then(({ rendered }) => rendered.html),\n\t\t\t\t\thead: promise.then(({ rendered }) => `${rendered.head}`),\n\t\t\t\t\tstyles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `` : ''))\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst { html, head, css } = mod.render(data);\n\n\t\t\t\tconst page = templates.render(200, {\n\t\t\t\t\tscripts: ``,\n\t\t\t\t\thtml,\n\t\t\t\t\thead: `${head}`,\n\t\t\t\t\tstyles: (css && css.code ? `` : '')\n\t\t\t\t});\n\n\t\t\t\tres.end(page);\n\t\t\t}\n\t\t}\n\n\t\telse {\n\t\t\tconst method = req.method.toLowerCase();\n\t\t\t// 'delete' cannot be exported from a module because it is a keyword,\n\t\t\t// so check for 'del' instead\n\t\t\tconst method_export = method === 'delete' ? 'del' : method;\n\t\t\tconst handler = mod[method_export];\n\t\t\tif (handler) {\n\t\t\t\thandler(req, res, next);\n\t\t\t} else {\n\t\t\t\t// no matching handler for method — 404\n\t\t\t\tnext();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn function find_route(req, res, next) {\n\t\tconst url = req.pathname;\n\n\t\t// whatever happens, we're going to serve some HTML\n\t\tres.setHeader('Content-Type', 'text/html');\n\n\t\tresolved\n\t\t\t.then(() => {\n\t\t\t\tfor (const route of route_manager.routes) {\n\t\t\t\t\tif (route.test(url)) return handle_route(route, req, res, next, fn());\n\t\t\t\t}\n\n\t\t\t\t// no matching route — 404\n\t\t\t\tnext();\n\t\t\t})\n\t\t\t.catch(err => {\n\t\t\t\tres.statusCode = 500;\n\t\t\t\tres.end(templates.render(500, {\n\t\t\t\t\ttitle: (err && err.name) || 'Internal server error',\n\t\t\t\t\turl,\n\t\t\t\t\terror: escape_html(err && (err.details || err.message || err) || 'Unknown error'),\n\t\t\t\t\tstack: err && err.stack.split('\\n').slice(1).join('\\n')\n\t\t\t\t}));\n\t\t\t});\n\t};\n}\n\nfunction get_not_found_handler(fn) {\n\treturn function handle_not_found(req, res) {\n\t\tconst asset_cache = fn();\n\n\t\tres.statusCode = 404;\n\t\tres.end(templates.render(404, {\n\t\t\ttitle: 'Not found',\n\t\t\tstatus: 404,\n\t\t\tmethod: req.method,\n\t\t\tscripts: ``,\n\t\t\turl: req.url\n\t\t}));\n\t};\n}\n\nfunction compose_handlers(handlers) {\n\treturn (req, res, next) => {\n\t\tlet i = 0;\n\t\tfunction go() {\n\t\t\tconst handler = handlers[i];\n\n\t\t\tif (handler) {\n\t\t\t\thandler(req, res, () => {\n\t\t\t\t\ti += 1;\n\t\t\t\t\tgo();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnext();\n\t\t\t}\n\t\t}\n\n\t\tgo();\n\t};\n}\n\nfunction read_json(file) {\n\treturn JSON.parse(fs.readFileSync(file, 'utf-8'));\n}\n\nfunction try_serialize(data) {\n\ttry {\n\t\treturn serialize(data);\n\t} catch (err) {\n\t\treturn null;\n\t}\n}"],"names":["templates","path.resolve","path.join","fs.writeFileSync","generate_asset_cache","compilers","create_app","route_manager","fs.readFileSync"],"mappings":"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"} \ No newline at end of file diff --git a/src/config.js b/src/config.js index 35f2d33..f685ca7 100644 --- a/src/config.js +++ b/src/config.js @@ -1,20 +1,11 @@ import * as path from 'path'; -import mkdirp from 'mkdirp'; -import rimraf from 'rimraf'; export const dev = process.env.NODE_ENV !== 'production'; export const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); - export const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); - export const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); -if (dev) { - mkdirp.sync(dest); - rimraf.sync(path.join(dest, '**/*')); -} - export const entry = { client: path.resolve(templates, '.main.rendered.js'), server: path.resolve(dest, 'server-entry.js') diff --git a/src/core/generate_asset_cache.js b/src/core/generate_asset_cache.js index 05546e1..ce82339 100644 --- a/src/core/generate_asset_cache.js +++ b/src/core/generate_asset_cache.js @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import glob from 'glob'; -import * as templates from './templates.js'; +import { create_templates, render } from './templates.js'; import * as route_manager from './route_manager.js'; function ensure_array(thing) { @@ -9,7 +9,7 @@ function ensure_array(thing) { } export default function generate_asset_cache({ src, dest, dev, client_info, server_info }) { - templates.create_templates(); // TODO refactor this... + create_templates(); // TODO refactor this... const main_file = `/client/${ensure_array(client_info.assetsByChunkName.main)[0]}`; @@ -71,7 +71,7 @@ function generate_service_worker({ chunk_files, src }) { } function generate_index(main_file) { - return templates.render(200, { + return render(200, { styles: '', head: '', html: '', diff --git a/src/core/utils/compilers.js b/src/core/utils/compilers.js index 4424d45..9c10cab 100644 --- a/src/core/utils/compilers.js +++ b/src/core/utils/compilers.js @@ -1,12 +1,9 @@ import * as path from 'path'; import relative from 'require-relative'; -const webpack = relative('webpack', process.cwd()); - -export let client; -export let server; - export function get_compilers() { + const webpack = relative('webpack', process.cwd()); + return { client: webpack( require(path.resolve('webpack.client.config.js')) @@ -16,12 +13,4 @@ export function get_compilers() { require(path.resolve('webpack.server.config.js')) ) }; -} - -// export const client = webpack( -// require(path.resolve('webpack.client.config.js')) -// ); - -// export const server = webpack( -// require(path.resolve('webpack.server.config.js')) -// ); \ No newline at end of file +} \ No newline at end of file diff --git a/src/core/utils/create_app.js b/src/core/utils/create_app.js index 4046482..003aa41 100644 --- a/src/core/utils/create_app.js +++ b/src/core/utils/create_app.js @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as route_manager from '../route_manager.js'; -import * as templates from '../templates.js'; +import { create_templates } from '../templates.js'; function posixify(file) { return file.replace(/[/\\]/g, '/'); @@ -90,7 +90,7 @@ export function start_watching({ src }) { }); watch('templates/**.html', () => { - templates.create_templates(); + create_templates(); // TODO reload current page? }); } diff --git a/src/middleware/index.js b/src/middleware/index.js index 525f483..aadb35e 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -1,5 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; +import mkdirp from 'mkdirp'; +import rimraf from 'rimraf'; import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; import { route_manager, templates, create_app, compilers, generate_asset_cache } from 'sapper/core.js'; @@ -7,6 +9,9 @@ import create_watcher from './create_watcher.js'; import { dest, dev, entry, src } from '../config.js'; function connect_dev() { + mkdirp.sync(dest); + rimraf.sync(path.join(dest, '**/*')); + create_app({ dev, entry, src }); const watcher = create_watcher(); diff --git a/webpack/config.js b/webpack/config.js deleted file mode 100644 index be6bfba..0000000 --- a/webpack/config.js +++ /dev/null @@ -1,71 +0,0 @@ -'use strict'; - -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - -var path = require('path'); -var mkdirp = _interopDefault(require('mkdirp')); -var rimraf = _interopDefault(require('rimraf')); - -const dev = process.env.NODE_ENV !== 'production'; - -const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates'); - -const src = path.resolve(process.env.SAPPER_ROUTES || 'routes'); - -const dest = path.resolve(process.env.SAPPER_DEST || '.sapper'); - -if (dev) { - mkdirp.sync(dest); - rimraf.sync(path.join(dest, '**/*')); -} - -const entry = { - client: path.resolve(templates, '.main.rendered.js'), - server: path.resolve(dest, 'server-entry.js') -}; - -var index = { - dev, - - client: { - entry: () => { - return { - main: [ - entry.client, - // workaround for https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456 - 'style-loader/lib/addStyles', - 'css-loader/lib/css-base' - ] - }; - }, - - output: () => { - return { - path: `${dest}/client`, - filename: '[name].[hash].js', - chunkFilename: '[name].[id].[hash].js', - publicPath: '/client/' - }; - } - }, - - server: { - entry: () => { - return { - main: entry.server - }; - }, - - output: () => { - return { - path: `${dest}/server`, - filename: '[name].[hash].js', - chunkFilename: '[name].[id].[hash].js', - libraryTarget: 'commonjs2' - }; - } - } -}; - -module.exports = index; -//# sourceMappingURL=config.js.map diff --git a/webpack/config.js.map b/webpack/config.js.map deleted file mode 100644 index 1be5aa7..0000000 --- a/webpack/config.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"config.js","sources":["../src/config.js","../src/webpack/index.js"],"sourcesContent":["import * as path from 'path';\nimport mkdirp from 'mkdirp';\nimport rimraf from 'rimraf';\n\nexport const dev = process.env.NODE_ENV !== 'production';\n\nexport const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates');\n\nexport const src = path.resolve(process.env.SAPPER_ROUTES || 'routes');\n\nexport const dest = path.resolve(process.env.SAPPER_DEST || '.sapper');\n\nif (dev) {\n\tmkdirp.sync(dest);\n\trimraf.sync(path.join(dest, '**/*'));\n}\n\nexport const entry = {\n\tclient: path.resolve(templates, '.main.rendered.js'),\n\tserver: path.resolve(dest, 'server-entry.js')\n};","import { dest, dev, entry } from '../config.js';\n\nexport default {\n\tdev,\n\n\tclient: {\n\t\tentry: () => {\n\t\t\treturn {\n\t\t\t\tmain: [\n\t\t\t\t\tentry.client,\n\t\t\t\t\t// workaround for https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/456\n\t\t\t\t\t'style-loader/lib/addStyles',\n\t\t\t\t\t'css-loader/lib/css-base'\n\t\t\t\t]\n\t\t\t};\n\t\t},\n\n\t\toutput: () => {\n\t\t\treturn {\n\t\t\t\tpath: `${dest}/client`,\n\t\t\t\tfilename: '[name].[hash].js',\n\t\t\t\tchunkFilename: '[name].[id].[hash].js',\n\t\t\t\tpublicPath: '/client/'\n\t\t\t};\n\t\t}\n\t},\n\n\tserver: {\n\t\tentry: () => {\n\t\t\treturn {\n\t\t\t\tmain: entry.server\n\t\t\t};\n\t\t},\n\n\t\toutput: () => {\n\t\t\treturn {\n\t\t\t\tpath: `${dest}/server`,\n\t\t\t\tfilename: '[name].[hash].js',\n\t\t\t\tchunkFilename: '[name].[id].[hash].js',\n\t\t\t\tlibraryTarget: 'commonjs2'\n\t\t\t};\n\t\t}\n\t}\n};\n"],"names":["path.resolve","path.join"],"mappings":";;;;;;;;AAIO,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;;AAEzD,AAAO,MAAM,SAAS,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW,CAAC,CAAC;;AAEnF,AAAO,MAAM,GAAG,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC;;AAEvE,AAAO,MAAM,IAAI,GAAGA,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,SAAS,CAAC,CAAC;;AAEvE,IAAI,GAAG,EAAE;CACR,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;CAClB,MAAM,CAAC,IAAI,CAACC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACrC;;AAED,AAAO,MAAM,KAAK,GAAG;CACpB,MAAM,EAAED,YAAY,CAAC,SAAS,EAAE,mBAAmB,CAAC;CACpD,MAAM,EAAEA,YAAY,CAAC,IAAI,EAAE,iBAAiB,CAAC;CAC7C;;AClBD,YAAe;CACd,GAAG;;CAEH,MAAM,EAAE;EACP,KAAK,EAAE,MAAM;GACZ,OAAO;IACN,IAAI,EAAE;KACL,KAAK,CAAC,MAAM;;KAEZ,4BAA4B;KAC5B,yBAAyB;KACzB;IACD,CAAC;GACF;;EAED,MAAM,EAAE,MAAM;GACb,OAAO;IACN,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;IACtB,QAAQ,EAAE,kBAAkB;IAC5B,aAAa,EAAE,uBAAuB;IACtC,UAAU,EAAE,UAAU;IACtB,CAAC;GACF;EACD;;CAED,MAAM,EAAE;EACP,KAAK,EAAE,MAAM;GACZ,OAAO;IACN,IAAI,EAAE,KAAK,CAAC,MAAM;IAClB,CAAC;GACF;;EAED,MAAM,EAAE,MAAM;GACb,OAAO;IACN,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;IACtB,QAAQ,EAAE,kBAAkB;IAC5B,aAAa,EAAE,uBAAuB;IACtC,aAAa,EAAE,WAAW;IAC1B,CAAC;GACF;EACD;CACD,CAAC;;;;"} \ No newline at end of file From fc631c4866ff1f59127792f16fb776ec9b17abec Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 15:41:13 -0500 Subject: [PATCH 5/9] make route handling more explicit --- src/core/build.js | 4 +- src/core/{utils => }/create_routes.js | 3 +- src/core/generate_asset_cache.js | 11 ++-- .../{utils/compilers.js => get_compilers.js} | 2 +- src/core/index.js | 7 ++- src/core/route_manager.js | 12 ----- src/core/utils/create_app.js | 50 +++++++++---------- src/middleware/create_watcher.js | 34 ++++++++++++- src/middleware/index.js | 26 +++++++--- test/unit/create_routes.test.js | 40 +++++++++++---- 10 files changed, 120 insertions(+), 69 deletions(-) rename src/core/{utils => }/create_routes.js (93%) rename src/core/{utils/compilers.js => get_compilers.js} (87%) delete mode 100644 src/core/route_manager.js diff --git a/src/core/build.js b/src/core/build.js index aaf6999..89fdfe2 100644 --- a/src/core/build.js +++ b/src/core/build.js @@ -4,7 +4,7 @@ import * as fs from 'fs'; import * as path from 'path'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; -import * as compilers from './utils/compilers.js'; +import get_compilers from './get_compilers.js'; import create_app from './utils/create_app.js'; import generate_asset_cache from './generate_asset_cache.js'; @@ -28,7 +28,7 @@ export default function build({ dest, dev, entry, src }) { } } - const { client, server } = compilers.get_compilers(); // TODO refactor + const { client, server } = get_compilers(); client.run((err, client_stats) => { handleErrors(err, client_stats); diff --git a/src/core/utils/create_routes.js b/src/core/create_routes.js similarity index 93% rename from src/core/utils/create_routes.js rename to src/core/create_routes.js index bf8d351..3a32870 100644 --- a/src/core/utils/create_routes.js +++ b/src/core/create_routes.js @@ -1,6 +1,7 @@ import * as path from 'path'; +import glob from 'glob'; -export default function create_routes(files) { +export default function create_routes({ src, files = glob.sync('**/*.+(html|js|mjs)', { cwd: src }) }) { const routes = files .map(file => { if (/(^|\/|\\)_/.test(file)) return; diff --git a/src/core/generate_asset_cache.js b/src/core/generate_asset_cache.js index ce82339..4a6ce9d 100644 --- a/src/core/generate_asset_cache.js +++ b/src/core/generate_asset_cache.js @@ -2,7 +2,7 @@ import * as fs from 'fs'; import * as path from 'path'; import glob from 'glob'; import { create_templates, render } from './templates.js'; -import * as route_manager from './route_manager.js'; +import create_routes from './create_routes.js'; function ensure_array(thing) { return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing @@ -18,6 +18,8 @@ export default function generate_asset_cache({ src, dest, dev, client_info, serv const service_worker = generate_service_worker({ chunk_files, src }); const index = generate_index(main_file); + const routes = create_routes({ src }); // TODO rename update + if (dev) { fs.writeFileSync(path.join(dest, 'service-worker.js'), service_worker); fs.writeFileSync(path.join(dest, 'index.html'), index); @@ -34,7 +36,8 @@ export default function generate_asset_cache({ src, dest, dev, client_info, serv return lookup; }, {}), - routes: route_manager.routes.reduce((lookup, route) => { + // TODO confusing that `routes` refers to an array *and* a lookup + routes: routes.reduce((lookup, route) => { lookup[route.id] = `/client/${ensure_array(client_info.assetsByChunkName[route.id])[0]}`; return lookup; }, {}), @@ -54,10 +57,10 @@ export default function generate_asset_cache({ src, dest, dev, client_info, serv function generate_service_worker({ chunk_files, src }) { const assets = glob.sync('**', { cwd: 'assets', nodir: true }); - route_manager.update({ src }); // TODO refactor + const routes = create_routes({ src }); // TODO refactor const route_code = `[${ - route_manager.routes + routes .filter(route => route.type === 'page') .map(route => `{ pattern: ${route.pattern} }`) .join(', ') diff --git a/src/core/utils/compilers.js b/src/core/get_compilers.js similarity index 87% rename from src/core/utils/compilers.js rename to src/core/get_compilers.js index 9c10cab..c835229 100644 --- a/src/core/utils/compilers.js +++ b/src/core/get_compilers.js @@ -1,7 +1,7 @@ import * as path from 'path'; import relative from 'require-relative'; -export function get_compilers() { +export default function get_compilers() { const webpack = relative('webpack', process.cwd()); return { diff --git a/src/core/index.js b/src/core/index.js index ee0513c..b07a0b1 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -1,11 +1,10 @@ -import * as route_manager from './route_manager.js'; import * as templates from './templates.js'; -import * as compilers from './utils/compilers.js'; export { default as build } from './build.js'; export { default as export } from './export.js'; export { default as generate_asset_cache } from './generate_asset_cache.js'; +export { default as get_compilers } from './get_compilers.js'; +export { default as create_routes } from './create_routes.js'; export { default as create_app } from './utils/create_app.js'; -export { default as create_routes } from './utils/create_routes.js'; -export { compilers, route_manager, templates }; \ No newline at end of file +export { templates }; \ No newline at end of file diff --git a/src/core/route_manager.js b/src/core/route_manager.js deleted file mode 100644 index 3d559b4..0000000 --- a/src/core/route_manager.js +++ /dev/null @@ -1,12 +0,0 @@ -import glob from 'glob'; -import create_routes from './utils/create_routes.js'; - -export let routes; - -export function update({ src }) { - routes = create_routes( - glob.sync('**/*.+(html|js|mjs)', { cwd: src }) - ); - - return routes; -} \ No newline at end of file diff --git a/src/core/utils/create_app.js b/src/core/utils/create_app.js index 003aa41..26c72a5 100644 --- a/src/core/utils/create_app.js +++ b/src/core/utils/create_app.js @@ -1,16 +1,14 @@ import * as fs from 'fs'; import * as path from 'path'; -import * as route_manager from '../route_manager.js'; -import { create_templates } from '../templates.js'; +import create_routes from '../create_routes.js'; +// import { create_templates } from '../templates.js'; function posixify(file) { return file.replace(/[/\\]/g, '/'); } function create_app({ src, dev, entry }) { - // const { routes } = route_manager; - route_manager.update({ src }); - const { routes } = route_manager; + const routes = create_routes({ src }); function create_client_main() { const template = fs.readFileSync('templates/main.js', 'utf-8'); @@ -68,31 +66,31 @@ function create_app({ src, dev, entry }) { create_server_routes(); } -export function start_watching({ src }) { - const chokidar = require('chokidar'); +// export function start_watching({ src }) { +// const chokidar = require('chokidar'); - const watch = (glob, callback) => { - const watcher = chokidar.watch(glob, { - ignoreInitial: true, - persistent: false - }); +// const watch = (glob, callback) => { +// const watcher = chokidar.watch(glob, { +// ignoreInitial: true, +// persistent: false +// }); - watcher.on('add', callback); - watcher.on('change', callback); - watcher.on('unlink', callback); - }; +// watcher.on('add', callback); +// watcher.on('change', callback); +// watcher.on('unlink', callback); +// }; - watch('templates/main.js', create_app); +// watch('templates/main.js', create_app); - watch('routes/**/*.+(html|js|mjs)', () => { - route_manager.update({ src }); - create_app(); - }); +// watch('routes/**/*.+(html|js|mjs)', () => { +// route_manager.update({ src }); +// create_app(); +// }); - watch('templates/**.html', () => { - create_templates(); - // TODO reload current page? - }); -} +// watch('templates/**.html', () => { +// create_templates(); +// // TODO reload current page? +// }); +// } export default create_app; diff --git a/src/middleware/create_watcher.js b/src/middleware/create_watcher.js index 6ae8f08..c0a61e4 100644 --- a/src/middleware/create_watcher.js +++ b/src/middleware/create_watcher.js @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import chalk from 'chalk'; -import { compilers, generate_asset_cache } from 'sapper/core.js'; +import { generate_asset_cache, create_routes } from 'sapper/core.js'; import { dest } from '../config.js'; function deferred() { @@ -15,7 +15,7 @@ function deferred() { return d; } -export default function create_watcher() { +export default function create_watcher({ compilers, src, onroutes }) { const deferreds = { client: deferred(), server: deferred() @@ -59,6 +59,36 @@ export default function create_watcher() { }); } + const chokidar = require('chokidar'); + + function watch_files(pattern, callback) { + const watcher = chokidar.watch(pattern, { + ignoreInitial: true, + persistent: false + }); + + watcher.on('add', callback); + watcher.on('change', callback); + watcher.on('unlink', callback); + + // watch('templates/main.js', create_app); + + // watch('routes/**/*.+(html|js|mjs)', () => { + // route_manager.update({ src }); + // create_app(); + // }); + + // watch('templates/**.html', () => { + // create_templates(); + // // TODO reload current page? + // }); + } + + watch_files('routes/**/*.+(html|js|mjs)', () => { + const routes = create_routes({ src }); + onroutes(routes); + }); + const watcher = { ready: invalidate(), client: watch_compiler('client'), diff --git a/src/middleware/index.js b/src/middleware/index.js index aadb35e..29d7ae6 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -4,7 +4,7 @@ import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; -import { route_manager, templates, create_app, compilers, generate_asset_cache } from 'sapper/core.js'; +import { create_routes, templates, create_app, get_compilers, generate_asset_cache } from 'sapper/core.js'; import create_watcher from './create_watcher.js'; import { dest, dev, entry, src } from '../config.js'; @@ -14,7 +14,16 @@ function connect_dev() { create_app({ dev, entry, src }); - const watcher = create_watcher(); + const compilers = get_compilers(); + + let routes; + + const watcher = create_watcher({ + compilers, + on_routes_update: _ => { + routes = _; + } + }); let asset_cache; @@ -55,7 +64,7 @@ function connect_dev() { fn: pathname => asset_cache.client.chunks[pathname] }), - get_route_handler(() => asset_cache), + get_route_handler(() => asset_cache, () => routes), get_not_found_handler(() => asset_cache) ]); @@ -76,6 +85,8 @@ function connect_prod() { server_info: read_json(path.join(dest, 'stats.server.json')) }); + const routes = create_routes({ src }); // TODO rename update + const middleware = compose_handlers([ set_req_pathname, @@ -100,7 +111,7 @@ function connect_prod() { fn: pathname => asset_cache.client.chunks[pathname] }), - get_route_handler(() => asset_cache), + get_route_handler(() => asset_cache, () => routes), get_not_found_handler(() => asset_cache) ]); @@ -132,7 +143,7 @@ function get_asset_handler(opts) { const resolved = Promise.resolve(); -function get_route_handler(fn) { +function get_route_handler(get_assets, get_routes) { function handle_route(route, req, res, next, { client, server }) { req.params = route.exec(req.pathname); @@ -204,8 +215,9 @@ function get_route_handler(fn) { resolved .then(() => { - for (const route of route_manager.routes) { - if (route.test(url)) return handle_route(route, req, res, next, fn()); + const routes = get_routes(); + for (const route of routes) { + if (route.test(url)) return handle_route(route, req, res, next, get_assets()); } // no matching route — 404 diff --git a/test/unit/create_routes.test.js b/test/unit/create_routes.test.js index 2ece078..e2828ed 100644 --- a/test/unit/create_routes.test.js +++ b/test/unit/create_routes.test.js @@ -3,7 +3,9 @@ const { create_routes } = require('../../core.js'); describe('create_routes', () => { it('sorts routes correctly', () => { - const routes = create_routes(['index.html', 'about.html', '[wildcard].html', 'post/foo.html', 'post/[id].html', 'post/bar.html']); + const routes = create_routes({ + files: ['index.html', 'about.html', '[wildcard].html', 'post/foo.html', 'post/[id].html', 'post/bar.html'] + }); assert.deepEqual( routes.map(r => r.file), @@ -19,7 +21,9 @@ describe('create_routes', () => { }); it('generates params', () => { - const routes = create_routes(['index.html', 'about.html', '[wildcard].html', 'post/[id].html']); + const routes = create_routes({ + files: ['index.html', 'about.html', '[wildcard].html', 'post/[id].html'] + }); let file; let params; @@ -38,7 +42,9 @@ describe('create_routes', () => { }); it('ignores files and directories with leading underscores', () => { - const routes = create_routes(['index.html', '_foo.html', 'a/_b/c/d.html', 'e/f/g/h.html', 'i/_j.html']); + const routes = create_routes({ + files: ['index.html', '_foo.html', 'a/_b/c/d.html', 'e/f/g/h.html', 'i/_j.html'] + }); assert.deepEqual( routes.map(r => r.file), @@ -50,8 +56,12 @@ describe('create_routes', () => { }); it('matches /foo/:bar before /:baz/qux', () => { - const a = create_routes(['foo/[bar].html', '[baz]/qux.html']); - const b = create_routes(['[baz]/qux.html', 'foo/[bar].html']); + const a = create_routes({ + files: ['foo/[bar].html', '[baz]/qux.html'] + }); + const b = create_routes({ + files: ['[baz]/qux.html', 'foo/[bar].html'] + }); assert.deepEqual( a.map(r => r.file), @@ -66,16 +76,22 @@ describe('create_routes', () => { it('fails if routes are indistinguishable', () => { assert.throws(() => { - create_routes(['[foo].html', '[bar]/index.html']); + create_routes({ + files: ['[foo].html', '[bar]/index.html'] + }); }, /The \[foo\].html and \[bar\]\/index.html routes clash/); assert.throws(() => { - create_routes(['foo.html', 'foo.js']); + create_routes({ + files: ['foo.html', 'foo.js'] + }); }, /The foo.html and foo.js routes clash/); }); it('matches nested routes', () => { - const route = create_routes(['settings/[submenu].html'])[0]; + const route = create_routes({ + files: ['settings/[submenu].html'] + })[0]; assert.deepEqual(route.exec('/settings/foo'), { submenu: 'foo' @@ -87,7 +103,9 @@ describe('create_routes', () => { }); it('prefers index routes to nested routes', () => { - const routes = create_routes(['settings/[submenu].html', 'settings.html']); + const routes = create_routes({ + files: ['settings/[submenu].html', 'settings.html'] + }); assert.deepEqual( routes.map(r => r.file), @@ -96,7 +114,9 @@ describe('create_routes', () => { }); it('matches deeply nested routes', () => { - const route = create_routes(['settings/[a]/[b]/index.html'])[0]; + const route = create_routes({ + files: ['settings/[a]/[b]/index.html'] + })[0]; assert.deepEqual(route.exec('/settings/foo/bar'), { a: 'foo', From fb8d952eeb43c3ee1f258d627aae87f08cab8e17 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 16:02:42 -0500 Subject: [PATCH 6/9] more tidying up --- src/core/build.js | 4 +--- src/core/{utils => }/create_app.js | 18 +++++++++--------- src/core/generate_asset_cache.js | 2 +- src/core/index.js | 2 +- src/middleware/create_watcher.js | 27 +++++++++++++-------------- src/middleware/index.js | 7 +++---- 6 files changed, 28 insertions(+), 32 deletions(-) rename src/core/{utils => }/create_app.js (82%) diff --git a/src/core/build.js b/src/core/build.js index 89fdfe2..3f0df53 100644 --- a/src/core/build.js +++ b/src/core/build.js @@ -1,11 +1,9 @@ -process.env.NODE_ENV = 'production'; - import * as fs from 'fs'; import * as path from 'path'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; import get_compilers from './get_compilers.js'; -import create_app from './utils/create_app.js'; +import create_app from './create_app.js'; import generate_asset_cache from './generate_asset_cache.js'; export default function build({ dest, dev, entry, src }) { diff --git a/src/core/utils/create_app.js b/src/core/create_app.js similarity index 82% rename from src/core/utils/create_app.js rename to src/core/create_app.js index 26c72a5..ea9ea96 100644 --- a/src/core/utils/create_app.js +++ b/src/core/create_app.js @@ -1,12 +1,17 @@ import * as fs from 'fs'; import * as path from 'path'; -import create_routes from '../create_routes.js'; -// import { create_templates } from '../templates.js'; +import create_routes from './create_routes.js'; function posixify(file) { return file.replace(/[/\\]/g, '/'); } +function fudge_mtime(file) { + // need to fudge the mtime so that webpack doesn't go doolally + const { atime, mtime } = fs.statSync(file); + fs.utimesSync(file, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); +} + function create_app({ src, dev, entry }) { const routes = create_routes({ src }); @@ -38,10 +43,7 @@ function create_app({ src, dev, entry }) { } fs.writeFileSync(entry.client, main); - - // need to fudge the mtime, because webpack is soft in the head - const { atime, mtime } = fs.statSync(entry.client); - fs.utimesSync(entry.client, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); + fudge_mtime(entry.client); } function create_server_routes() { @@ -57,9 +59,7 @@ function create_app({ src, dev, entry }) { const exports = `export { ${routes.map(route => route.id)} };`; fs.writeFileSync(entry.server, `${imports}\n\n${exports}`); - - const { atime, mtime } = fs.statSync(entry.server); - fs.utimesSync(entry.server, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); + fudge_mtime(entry.server); } create_client_main(); diff --git a/src/core/generate_asset_cache.js b/src/core/generate_asset_cache.js index 4a6ce9d..1f65a6a 100644 --- a/src/core/generate_asset_cache.js +++ b/src/core/generate_asset_cache.js @@ -18,7 +18,7 @@ export default function generate_asset_cache({ src, dest, dev, client_info, serv const service_worker = generate_service_worker({ chunk_files, src }); const index = generate_index(main_file); - const routes = create_routes({ src }); // TODO rename update + const routes = create_routes({ src }); if (dev) { fs.writeFileSync(path.join(dest, 'service-worker.js'), service_worker); diff --git a/src/core/index.js b/src/core/index.js index b07a0b1..5b26df4 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -5,6 +5,6 @@ export { default as export } from './export.js'; export { default as generate_asset_cache } from './generate_asset_cache.js'; export { default as get_compilers } from './get_compilers.js'; export { default as create_routes } from './create_routes.js'; -export { default as create_app } from './utils/create_app.js'; +export { default as create_app } from './create_app.js'; export { templates }; \ No newline at end of file diff --git a/src/middleware/create_watcher.js b/src/middleware/create_watcher.js index c0a61e4..dd71321 100644 --- a/src/middleware/create_watcher.js +++ b/src/middleware/create_watcher.js @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import chalk from 'chalk'; -import { generate_asset_cache, create_routes } from 'sapper/core.js'; +import { generate_asset_cache, create_routes, create_app } from 'sapper/core.js'; import { dest } from '../config.js'; function deferred() { @@ -15,7 +15,7 @@ function deferred() { return d; } -export default function create_watcher({ compilers, src, onroutes }) { +export default function create_watcher({ compilers, dev, entry, src, onroutes }) { const deferreds = { client: deferred(), server: deferred() @@ -31,10 +31,11 @@ export default function create_watcher({ compilers, src, onroutes }) { const server_info = server_stats.toJson(); fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(server_info, null, ' ')); - return generate_asset_cache( - client_stats.toJson(), - server_stats.toJson() - ); + return generate_asset_cache({ + src, dest, dev, + client_info: client_stats.toJson(), + server_info: server_stats.toJson() + }); }); function watch_compiler(type) { @@ -63,7 +64,6 @@ export default function create_watcher({ compilers, src, onroutes }) { function watch_files(pattern, callback) { const watcher = chokidar.watch(pattern, { - ignoreInitial: true, persistent: false }); @@ -71,13 +71,6 @@ export default function create_watcher({ compilers, src, onroutes }) { watcher.on('change', callback); watcher.on('unlink', callback); - // watch('templates/main.js', create_app); - - // watch('routes/**/*.+(html|js|mjs)', () => { - // route_manager.update({ src }); - // create_app(); - // }); - // watch('templates/**.html', () => { // create_templates(); // // TODO reload current page? @@ -87,6 +80,12 @@ export default function create_watcher({ compilers, src, onroutes }) { watch_files('routes/**/*.+(html|js|mjs)', () => { const routes = create_routes({ src }); onroutes(routes); + + create_app({ dev, entry, src }); // TODO this calls `create_routes` again, we should pass `routes` to `create_app` instead + }); + + watch_files('templates/main.js', () => { + create_app({ dev, entry, src }); }); const watcher = { diff --git a/src/middleware/index.js b/src/middleware/index.js index 29d7ae6..3bb39c6 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -4,7 +4,7 @@ import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; -import { create_routes, templates, create_app, get_compilers, generate_asset_cache } from 'sapper/core.js'; +import { create_routes, templates, get_compilers, generate_asset_cache } from 'sapper/core.js'; import create_watcher from './create_watcher.js'; import { dest, dev, entry, src } from '../config.js'; @@ -12,15 +12,14 @@ function connect_dev() { mkdirp.sync(dest); rimraf.sync(path.join(dest, '**/*')); - create_app({ dev, entry, src }); - const compilers = get_compilers(); let routes; const watcher = create_watcher({ + dev, entry, src, compilers, - on_routes_update: _ => { + onroutes: _ => { routes = _; } }); From 4940644ae33b0ec21942c83c42c7265f8e7c631b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 16:11:46 -0500 Subject: [PATCH 7/9] more tidying up --- src/core/build.js | 8 ++++---- src/core/create_app.js | 4 +--- src/core/{generate_asset_cache.js => create_assets.js} | 4 ++-- src/core/{get_compilers.js => create_compilers.js} | 2 +- src/core/export.js | 4 ++-- src/core/index.js | 6 +++--- src/core/templates.js | 2 ++ src/middleware/create_watcher.js | 4 ++-- src/middleware/index.js | 6 +++--- 9 files changed, 20 insertions(+), 20 deletions(-) rename src/core/{generate_asset_cache.js => create_assets.js} (94%) rename src/core/{get_compilers.js => create_compilers.js} (86%) diff --git a/src/core/build.js b/src/core/build.js index 3f0df53..48c0844 100644 --- a/src/core/build.js +++ b/src/core/build.js @@ -2,9 +2,9 @@ import * as fs from 'fs'; import * as path from 'path'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; -import get_compilers from './get_compilers.js'; +import create_compilers from './create_compilers.js'; import create_app from './create_app.js'; -import generate_asset_cache from './generate_asset_cache.js'; +import create_assets from './create_assets.js'; export default function build({ dest, dev, entry, src }) { mkdirp.sync(dest); @@ -26,7 +26,7 @@ export default function build({ dest, dev, entry, src }) { } } - const { client, server } = get_compilers(); + const { client, server } = create_compilers(); client.run((err, client_stats) => { handleErrors(err, client_stats); @@ -38,7 +38,7 @@ export default function build({ dest, dev, entry, src }) { const server_info = server_stats.toJson(); fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(server_info, null, ' ')); - generate_asset_cache({ src, dest, dev, client_info, server_info }); + create_assets({ src, dest, dev, client_info, server_info }); fulfil(); }); }); diff --git a/src/core/create_app.js b/src/core/create_app.js index ea9ea96..a65f4dd 100644 --- a/src/core/create_app.js +++ b/src/core/create_app.js @@ -16,8 +16,6 @@ function create_app({ src, dev, entry }) { const routes = create_routes({ src }); function create_client_main() { - const template = fs.readFileSync('templates/main.js', 'utf-8'); - const code = `[${ routes .filter(route => route.type === 'page') @@ -32,7 +30,7 @@ function create_app({ src, dev, entry }) { .join(', ') }]`; - let main = template + let main = fs.readFileSync('templates/main.js', 'utf-8') .replace(/__app__/g, posixify(path.resolve(__dirname, '../../runtime/app.js'))) .replace(/__routes__/g, code) .replace(/__dev__/g, String(dev)); diff --git a/src/core/generate_asset_cache.js b/src/core/create_assets.js similarity index 94% rename from src/core/generate_asset_cache.js rename to src/core/create_assets.js index 1f65a6a..438e5f2 100644 --- a/src/core/generate_asset_cache.js +++ b/src/core/create_assets.js @@ -8,7 +8,7 @@ function ensure_array(thing) { return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing } -export default function generate_asset_cache({ src, dest, dev, client_info, server_info }) { +export default function create_assets({ src, dest, dev, client_info, server_info }) { create_templates(); // TODO refactor this... const main_file = `/client/${ensure_array(client_info.assetsByChunkName.main)[0]}`; @@ -20,7 +20,7 @@ export default function generate_asset_cache({ src, dest, dev, client_info, serv const routes = create_routes({ src }); - if (dev) { + if (dev) { // TODO move this into calling code fs.writeFileSync(path.join(dest, 'service-worker.js'), service_worker); fs.writeFileSync(path.join(dest, 'index.html'), index); } diff --git a/src/core/get_compilers.js b/src/core/create_compilers.js similarity index 86% rename from src/core/get_compilers.js rename to src/core/create_compilers.js index c835229..b410890 100644 --- a/src/core/get_compilers.js +++ b/src/core/create_compilers.js @@ -1,7 +1,7 @@ import * as path from 'path'; import relative from 'require-relative'; -export default function get_compilers() { +export default function create_compilers() { const webpack = relative('webpack', process.cwd()); return { diff --git a/src/core/export.js b/src/core/export.js index 7416c36..069c232 100644 --- a/src/core/export.js +++ b/src/core/export.js @@ -4,7 +4,7 @@ import express from 'express'; import cheerio from 'cheerio'; import fetch from 'node-fetch'; import URL from 'url-parse'; -import generate_asset_cache from './generate_asset_cache.js'; +import create_assets from './create_assets.js'; // import middleware from '../middleware/index.js'; const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env; @@ -21,7 +21,7 @@ export default function exporter({ src, dest }) { // TODO dest is a terrible nam // Prep output directory sander.rimrafSync(OUTPUT_DIR); - const { service_worker } = generate_asset_cache({ + const { service_worker } = create_assets({ src, dest, dev: false, client_info: read_json(path.join(dest, 'stats.client.json')), diff --git a/src/core/index.js b/src/core/index.js index 5b26df4..a085272 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -1,9 +1,9 @@ -import * as templates from './templates.js'; +import * as templates from './templates.js'; // TODO templates is an anomaly... fix post-#91 export { default as build } from './build.js'; export { default as export } from './export.js'; -export { default as generate_asset_cache } from './generate_asset_cache.js'; -export { default as get_compilers } from './get_compilers.js'; +export { default as create_assets } from './create_assets.js'; +export { default as create_compilers } from './create_compilers.js'; export { default as create_routes } from './create_routes.js'; export { default as create_app } from './create_app.js'; diff --git a/src/core/templates.js b/src/core/templates.js index c95a07e..d0862a0 100644 --- a/src/core/templates.js +++ b/src/core/templates.js @@ -96,6 +96,8 @@ export function create_templates() { }; }) .sort((a, b) => b.specificity - a.specificity); + + return templates; } export function render(status, data) { diff --git a/src/middleware/create_watcher.js b/src/middleware/create_watcher.js index dd71321..0b65998 100644 --- a/src/middleware/create_watcher.js +++ b/src/middleware/create_watcher.js @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import chalk from 'chalk'; -import { generate_asset_cache, create_routes, create_app } from 'sapper/core.js'; +import { create_assets, create_routes, create_app } from 'sapper/core.js'; import { dest } from '../config.js'; function deferred() { @@ -31,7 +31,7 @@ export default function create_watcher({ compilers, dev, entry, src, onroutes }) const server_info = server_stats.toJson(); fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(server_info, null, ' ')); - return generate_asset_cache({ + return create_assets({ src, dest, dev, client_info: client_stats.toJson(), server_info: server_stats.toJson() diff --git a/src/middleware/index.js b/src/middleware/index.js index 3bb39c6..d349b8f 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -4,7 +4,7 @@ import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; -import { create_routes, templates, get_compilers, generate_asset_cache } from 'sapper/core.js'; +import { create_routes, templates, create_compilers, create_assets } from 'sapper/core.js'; import create_watcher from './create_watcher.js'; import { dest, dev, entry, src } from '../config.js'; @@ -12,7 +12,7 @@ function connect_dev() { mkdirp.sync(dest); rimraf.sync(path.join(dest, '**/*')); - const compilers = get_compilers(); + const compilers = create_compilers(); let routes; @@ -77,7 +77,7 @@ function connect_dev() { } function connect_prod() { - const asset_cache = generate_asset_cache({ + const asset_cache = create_assets({ src, dest, dev: false, client_info: read_json(path.join(dest, 'stats.client.json')), From fd0dd4fe58eee3dd0b3a707d7e546a6a79ae50b2 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 16:14:16 -0500 Subject: [PATCH 8/9] and again... --- src/core/create_assets.js | 2 +- src/middleware/create_watcher.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/create_assets.js b/src/core/create_assets.js index 438e5f2..9b31f51 100644 --- a/src/core/create_assets.js +++ b/src/core/create_assets.js @@ -57,7 +57,7 @@ export default function create_assets({ src, dest, dev, client_info, server_info function generate_service_worker({ chunk_files, src }) { const assets = glob.sync('**', { cwd: 'assets', nodir: true }); - const routes = create_routes({ src }); // TODO refactor + const routes = create_routes({ src }); const route_code = `[${ routes diff --git a/src/middleware/create_watcher.js b/src/middleware/create_watcher.js index 0b65998..cbd4477 100644 --- a/src/middleware/create_watcher.js +++ b/src/middleware/create_watcher.js @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import chalk from 'chalk'; -import { create_assets, create_routes, create_app } from 'sapper/core.js'; +import { create_app, create_assets, create_routes, create_templates } from 'sapper/core.js'; import { dest } from '../config.js'; function deferred() { @@ -70,11 +70,6 @@ export default function create_watcher({ compilers, dev, entry, src, onroutes }) watcher.on('add', callback); watcher.on('change', callback); watcher.on('unlink', callback); - - // watch('templates/**.html', () => { - // create_templates(); - // // TODO reload current page? - // }); } watch_files('routes/**/*.+(html|js|mjs)', () => { @@ -88,6 +83,11 @@ export default function create_watcher({ compilers, dev, entry, src, onroutes }) create_app({ dev, entry, src }); }); + watch_files('templates/**.html', () => { + create_templates(); + // TODO reload current page? + }); + const watcher = { ready: invalidate(), client: watch_compiler('client'), From 8bad37205d2ca954fc1e13c064cdd4cf6749defa Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 21 Jan 2018 16:28:02 -0500 Subject: [PATCH 9/9] convert to typescript --- package-lock.json | 42 +++++++++ package.json | 3 + rollup.config.js | 8 +- src/cli/{index.js => index.ts} | 2 +- src/{config.js => config.ts} | 0 src/core/{build.js => build.ts} | 22 ++++- src/core/create_app.js | 94 ------------------- src/core/create_app.ts | 90 ++++++++++++++++++ .../{create_assets.js => create_assets.ts} | 4 +- ...reate_compilers.js => create_compilers.ts} | 0 .../{create_routes.js => create_routes.ts} | 0 src/core/{export.js => export.ts} | 0 src/core/index.js | 10 -- src/core/index.ts | 11 +++ src/core/{templates.js => templates.ts} | 0 .../{create_watcher.js => create_watcher.ts} | 4 +- src/middleware/{index.js => index.ts} | 4 +- src/webpack/{index.js => index.ts} | 2 +- 18 files changed, 177 insertions(+), 119 deletions(-) rename src/cli/{index.js => index.ts} (94%) rename src/{config.js => config.ts} (100%) rename src/core/{build.js => build.ts} (73%) delete mode 100644 src/core/create_app.js create mode 100644 src/core/create_app.ts rename src/core/{create_assets.js => create_assets.ts} (95%) rename src/core/{create_compilers.js => create_compilers.ts} (100%) rename src/core/{create_routes.js => create_routes.ts} (100%) rename src/core/{export.js => export.ts} (100%) delete mode 100644 src/core/index.js create mode 100644 src/core/index.ts rename src/core/{templates.js => templates.ts} (100%) rename src/middleware/{create_watcher.js => create_watcher.ts} (95%) rename src/middleware/{index.js => index.ts} (98%) rename src/webpack/{index.js => index.ts} (93%) diff --git a/package-lock.json b/package-lock.json index 4907693..f5fb1e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,53 @@ "integrity": "sha512-bPBbpu1vqgOOD70aMVG5tgioPdttKXQQFq6xodjZxVbPprtZIcm8NcTEJoB+/1QoH8z1TIqjaEN1Wm3YndnfNQ==", "dev": true }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==", + "dev": true + }, + "@types/glob": { + "version": "5.0.34", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.34.tgz", + "integrity": "sha512-sUvpieq+HsWTLdkeOI8Mi8u22Ag3AoGuM3sv+XMP1bKtbaIAHpEA2f52K2mz6vK5PVhTa3bFyRZLZMqTxOo2Cw==", + "dev": true, + "requires": { + "@types/events": "1.1.0", + "@types/minimatch": "3.0.3", + "@types/node": "9.3.0" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/mkdirp": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", + "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", + "dev": true, + "requires": { + "@types/node": "9.3.0" + } + }, "@types/node": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-9.3.0.tgz", "integrity": "sha512-wNBfvNjzsJl4tswIZKXCFQY0lss9nKUyJnG6T94X/eqjRgI2jHZ4evdjhQYBSan/vGtF6XVXPApOmNH2rf0KKw==" }, + "@types/rimraf": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.2.tgz", + "integrity": "sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ==", + "dev": true, + "requires": { + "@types/glob": "5.0.34", + "@types/node": "9.3.0" + } + }, "@types/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", diff --git a/package.json b/package.json index f6ddf51..6d58c16 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,9 @@ }, "devDependencies": { "@std/esm": "^0.19.7", + "@types/glob": "^5.0.34", + "@types/mkdirp": "^0.5.2", + "@types/rimraf": "^2.0.2", "css-loader": "^0.28.7", "eslint": "^4.13.1", "eslint-plugin-import": "^2.8.0", diff --git a/rollup.config.js b/rollup.config.js index f088d8a..9314270 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -14,7 +14,7 @@ const paths = { export default [ // cli.js { - input: 'src/cli/index.js', + input: 'src/cli/index.ts', output: { file: 'cli.js', format: 'cjs', @@ -32,7 +32,7 @@ export default [ // core.js { - input: 'src/core/index.js', + input: 'src/core/index.ts', output: { file: 'core.js', format: 'cjs', @@ -50,7 +50,7 @@ export default [ // middleware.js { - input: 'src/middleware/index.js', + input: 'src/middleware/index.ts', output: { file: 'middleware.js', format: 'cjs', @@ -84,7 +84,7 @@ export default [ // webpack/config.js { - input: 'src/webpack/index.js', + input: 'src/webpack/index.ts', output: { file: 'webpack/config.js', format: 'cjs', diff --git a/src/cli/index.js b/src/cli/index.ts similarity index 94% rename from src/cli/index.js rename to src/cli/index.ts index 2ce467b..cb15dc7 100755 --- a/src/cli/index.js +++ b/src/cli/index.ts @@ -1,5 +1,5 @@ import { build, export as exporter } from 'sapper/core.js'; -import { dest, dev, entry, src } from '../config.js'; +import { dest, dev, entry, src } from '../config'; const cmd = process.argv[2]; const start = Date.now(); diff --git a/src/config.js b/src/config.ts similarity index 100% rename from src/config.js rename to src/config.ts diff --git a/src/core/build.js b/src/core/build.ts similarity index 73% rename from src/core/build.js rename to src/core/build.ts index 48c0844..475b928 100644 --- a/src/core/build.js +++ b/src/core/build.ts @@ -6,7 +6,17 @@ import create_compilers from './create_compilers.js'; import create_app from './create_app.js'; import create_assets from './create_assets.js'; -export default function build({ dest, dev, entry, src }) { +export default function build({ + src, + dest, + dev, + entry +}: { + src: string; + dest: string; + dev: boolean; + entry: { client: string, server: string } +}) { mkdirp.sync(dest); rimraf.sync(path.join(dest, '**/*')); @@ -31,12 +41,18 @@ export default function build({ dest, dev, entry, src }) { client.run((err, client_stats) => { handleErrors(err, client_stats); const client_info = client_stats.toJson(); - fs.writeFileSync(path.join(dest, 'stats.client.json'), JSON.stringify(client_info, null, ' ')); + fs.writeFileSync( + path.join(dest, 'stats.client.json'), + JSON.stringify(client_info, null, ' ') + ); server.run((err, server_stats) => { handleErrors(err, server_stats); const server_info = server_stats.toJson(); - fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(server_info, null, ' ')); + fs.writeFileSync( + path.join(dest, 'stats.server.json'), + JSON.stringify(server_info, null, ' ') + ); create_assets({ src, dest, dev, client_info, server_info }); fulfil(); diff --git a/src/core/create_app.js b/src/core/create_app.js deleted file mode 100644 index a65f4dd..0000000 --- a/src/core/create_app.js +++ /dev/null @@ -1,94 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import create_routes from './create_routes.js'; - -function posixify(file) { - return file.replace(/[/\\]/g, '/'); -} - -function fudge_mtime(file) { - // need to fudge the mtime so that webpack doesn't go doolally - const { atime, mtime } = fs.statSync(file); - fs.utimesSync(file, new Date(atime.getTime() - 999999), new Date(mtime.getTime() - 999999)); -} - -function create_app({ src, dev, entry }) { - const routes = create_routes({ src }); - - function create_client_main() { - const code = `[${ - routes - .filter(route => route.type === 'page') - .map(route => { - const params = route.dynamic.length === 0 ? - '{}' : - `{ ${route.dynamic.map((part, i) => `${part}: match[${i + 1}]`).join(', ') } }`; - - const file = posixify(`${src}/${route.file}`); - return `{ pattern: ${route.pattern}, params: match => (${params}), load: () => import(/* webpackChunkName: "${route.id}" */ '${file}') }` - }) - .join(', ') - }]`; - - let main = fs.readFileSync('templates/main.js', 'utf-8') - .replace(/__app__/g, posixify(path.resolve(__dirname, '../../runtime/app.js'))) - .replace(/__routes__/g, code) - .replace(/__dev__/g, String(dev)); - - if (dev) { - const hmr_client = posixify(require.resolve(`webpack-hot-middleware/client`)); - main += `\n\nimport('${hmr_client}?path=/__webpack_hmr&timeout=20000'); if (module.hot) module.hot.accept();` - } - - fs.writeFileSync(entry.client, main); - fudge_mtime(entry.client); - } - - function create_server_routes() { - const imports = routes - .map(route => { - const file = posixify(`${src}/${route.file}`); - return route.type === 'page' ? - `import ${route.id} from '${file}';` : - `import * as ${route.id} from '${file}';`; - }) - .join('\n'); - - const exports = `export { ${routes.map(route => route.id)} };`; - - fs.writeFileSync(entry.server, `${imports}\n\n${exports}`); - fudge_mtime(entry.server); - } - - create_client_main(); - create_server_routes(); -} - -// export function start_watching({ src }) { -// const chokidar = require('chokidar'); - -// const watch = (glob, callback) => { -// const watcher = chokidar.watch(glob, { -// ignoreInitial: true, -// persistent: false -// }); - -// watcher.on('add', callback); -// watcher.on('change', callback); -// watcher.on('unlink', callback); -// }; - -// watch('templates/main.js', create_app); - -// watch('routes/**/*.+(html|js|mjs)', () => { -// route_manager.update({ src }); -// create_app(); -// }); - -// watch('templates/**.html', () => { -// create_templates(); -// // TODO reload current page? -// }); -// } - -export default create_app; diff --git a/src/core/create_app.ts b/src/core/create_app.ts new file mode 100644 index 0000000..c62dee1 --- /dev/null +++ b/src/core/create_app.ts @@ -0,0 +1,90 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import create_routes from './create_routes'; + +function posixify(file: string) { + return file.replace(/[/\\]/g, '/'); +} + +function fudge_mtime(file: string) { + // need to fudge the mtime so that webpack doesn't go doolally + const { atime, mtime } = fs.statSync(file); + fs.utimesSync( + file, + new Date(atime.getTime() - 999999), + new Date(mtime.getTime() - 999999) + ); +} + +function create_app({ + src, + dev, + entry +}: { + src: string; + dev: boolean; + entry: { client: string; server: string }; +}) { + const routes = create_routes({ src }); + + function create_client_main() { + const code = `[${routes + .filter(route => route.type === 'page') + .map(route => { + const params = + route.dynamic.length === 0 + ? '{}' + : `{ ${route.dynamic + .map((part, i) => `${part}: match[${i + 1}]`) + .join(', ')} }`; + + const file = posixify(`${src}/${route.file}`); + return `{ pattern: ${ + route.pattern + }, params: match => (${params}), load: () => import(/* webpackChunkName: "${ + route.id + }" */ '${file}') }`; + }) + .join(', ')}]`; + + let main = fs + .readFileSync('templates/main.js', 'utf-8') + .replace( + /__app__/g, + posixify(path.resolve(__dirname, '../../runtime/app.js')) + ) + .replace(/__routes__/g, code) + .replace(/__dev__/g, String(dev)); + + if (dev) { + const hmr_client = posixify( + require.resolve(`webpack-hot-middleware/client`) + ); + main += `\n\nimport('${hmr_client}?path=/__webpack_hmr&timeout=20000'); if (module.hot) module.hot.accept();`; + } + + fs.writeFileSync(entry.client, main); + fudge_mtime(entry.client); + } + + function create_server_routes() { + const imports = routes + .map(route => { + const file = posixify(`${src}/${route.file}`); + return route.type === 'page' + ? `import ${route.id} from '${file}';` + : `import * as ${route.id} from '${file}';`; + }) + .join('\n'); + + const exports = `export { ${routes.map(route => route.id)} };`; + + fs.writeFileSync(entry.server, `${imports}\n\n${exports}`); + fudge_mtime(entry.server); + } + + create_client_main(); + create_server_routes(); +} + +export default create_app; diff --git a/src/core/create_assets.js b/src/core/create_assets.ts similarity index 95% rename from src/core/create_assets.js rename to src/core/create_assets.ts index 9b31f51..57f0659 100644 --- a/src/core/create_assets.js +++ b/src/core/create_assets.ts @@ -1,8 +1,8 @@ import * as fs from 'fs'; import * as path from 'path'; import glob from 'glob'; -import { create_templates, render } from './templates.js'; -import create_routes from './create_routes.js'; +import { create_templates, render } from './templates'; +import create_routes from './create_routes'; function ensure_array(thing) { return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing diff --git a/src/core/create_compilers.js b/src/core/create_compilers.ts similarity index 100% rename from src/core/create_compilers.js rename to src/core/create_compilers.ts diff --git a/src/core/create_routes.js b/src/core/create_routes.ts similarity index 100% rename from src/core/create_routes.js rename to src/core/create_routes.ts diff --git a/src/core/export.js b/src/core/export.ts similarity index 100% rename from src/core/export.js rename to src/core/export.ts diff --git a/src/core/index.js b/src/core/index.js deleted file mode 100644 index a085272..0000000 --- a/src/core/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import * as templates from './templates.js'; // TODO templates is an anomaly... fix post-#91 - -export { default as build } from './build.js'; -export { default as export } from './export.js'; -export { default as create_assets } from './create_assets.js'; -export { default as create_compilers } from './create_compilers.js'; -export { default as create_routes } from './create_routes.js'; -export { default as create_app } from './create_app.js'; - -export { templates }; \ No newline at end of file diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 0000000..b557348 --- /dev/null +++ b/src/core/index.ts @@ -0,0 +1,11 @@ +import { create_templates, render, stream } from './templates'; // TODO templates is an anomaly... fix post-#91 + +export { default as build } from './build'; +export { default as export } from './export.js'; + +export { default as create_app } from './create_app'; +export { default as create_assets } from './create_assets'; +export { default as create_compilers } from './create_compilers'; +export { default as create_routes } from './create_routes'; + +export const templates = { create_templates, render, stream }; \ No newline at end of file diff --git a/src/core/templates.js b/src/core/templates.ts similarity index 100% rename from src/core/templates.js rename to src/core/templates.ts diff --git a/src/middleware/create_watcher.js b/src/middleware/create_watcher.ts similarity index 95% rename from src/middleware/create_watcher.js rename to src/middleware/create_watcher.ts index cbd4477..dd8f171 100644 --- a/src/middleware/create_watcher.js +++ b/src/middleware/create_watcher.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; import chalk from 'chalk'; -import { create_app, create_assets, create_routes, create_templates } from 'sapper/core.js'; +import { create_app, create_assets, create_routes, templates } from 'sapper/core.js'; import { dest } from '../config.js'; function deferred() { @@ -84,7 +84,7 @@ export default function create_watcher({ compilers, dev, entry, src, onroutes }) }); watch_files('templates/**.html', () => { - create_templates(); + templates.create_templates(); // TODO reload current page? }); diff --git a/src/middleware/index.js b/src/middleware/index.ts similarity index 98% rename from src/middleware/index.js rename to src/middleware/index.ts index d349b8f..bbb88c7 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.ts @@ -5,8 +5,8 @@ import rimraf from 'rimraf'; import serialize from 'serialize-javascript'; import escape_html from 'escape-html'; import { create_routes, templates, create_compilers, create_assets } from 'sapper/core.js'; -import create_watcher from './create_watcher.js'; -import { dest, dev, entry, src } from '../config.js'; +import create_watcher from './create_watcher'; +import { dest, dev, entry, src } from '../config'; function connect_dev() { mkdirp.sync(dest); diff --git a/src/webpack/index.js b/src/webpack/index.ts similarity index 93% rename from src/webpack/index.js rename to src/webpack/index.ts index 5c50bab..4cf620e 100644 --- a/src/webpack/index.js +++ b/src/webpack/index.ts @@ -1,4 +1,4 @@ -import { dest, dev, entry } from '../config.js'; +import { dest, dev, entry } from '../config'; export default { dev,