Compare commits

...

28 Commits

Author SHA1 Message Date
Rich Harris
8faa98af6a -> v0.4.0 2018-01-14 12:07:06 -05:00
Rich Harris
14df138528 Merge pull request #87 from sveltejs/gh-3
Serialize preloaded data for initial page and serve to client
2018-01-14 11:50:18 -05:00
Rich Harris
44285cdb2f serialized preloaded data and send to client as initial payload - fixes #3 2018-01-14 11:22:00 -05:00
Rich Harris
bd656cfd5b Merge branch 'fix-tests-without-async' into gh-3 2018-01-14 10:45:55 -05:00
Rich Harris
c4b4bd587d use %sapper.scripts% 2018-01-14 10:45:21 -05:00
Rich Harris
2abfdb03d5 wait for window.READY so that this tests we dont double-preload 2018-01-14 10:44:38 -05:00
Rich Harris
a80ac3a8b8 change tests back to non-async versions 2018-01-14 00:43:57 -05:00
Rich Harris
887cb09386 merge 2018-01-14 00:21:55 -05:00
Rich Harris
cfeeafded4 Merge pull request #84 from sveltejs/test-in-node-6
test in node 6
2018-01-14 00:18:23 -05:00
Rich Harris
2cae674033 Merge branch 'master' into test-in-node-6 2018-01-14 00:14:40 -05:00
Rich Harris
7c0f32662d remove async from new test 2018-01-14 00:10:20 -05:00
Rich Harris
b4fb1c3268 Merge branch 'master' of github.com:sveltejs/sapper 2018-01-14 00:02:32 -05:00
Rich Harris
ecd0f673a9 test in node 6 2018-01-14 00:01:51 -05:00
Rich Harris
40d16852f7 prevent unnecessary promise chains, and hoist handler function 2018-01-14 00:01:10 -05:00
Rich Harris
133be03791 Merge pull request #72 from nolanlawson/fix-style-loader
Explicitly load style-loader/css-loader deps
2018-01-13 23:33:38 -05:00
Rich Harris
727a76ebb5 fall through to 404 if no handler exists for method 2018-01-13 23:29:41 -05:00
Rich Harris
e3c047831a add test for #77 2018-01-13 23:29:16 -05:00
Emil Tholin
81b5e0d764 Handle DELETE requests with del export 2018-01-10 19:24:22 +01:00
Emil Tholin
98e904dcfc Remove async/await from test.js 2018-01-07 12:22:40 +01:00
Nolan Lawson
ca51372150 Explicitly load style-loader/css-loader deps
This appears to fix sveltejs/sapper-template#27
2018-01-06 17:21:40 -08:00
Luke Edwards
7cef1f1120 only return from show-url if in server context 2018-01-06 16:11:39 -08:00
Luke Edwards
1b73baabce [temp - debug]: log out the preload value 2018-01-06 15:40:40 -08:00
Luke Edwards
5aa01b922b add page.title() Nightmare action 2018-01-06 15:16:18 -08:00
Luke Edwards
f0bc68be88 use built-in for document.title 2018-01-06 15:07:43 -08:00
Luke Edwards
be7c53becc quick attempt at fixing test for travis 2018-01-06 14:53:14 -08:00
Emil Tholin
2b3472b1b1 Remove async/await from lib 2018-01-05 23:19:40 +01:00
Rich Harris
ee94f355d5 update marked due to vulnerability 2018-01-04 17:17:08 -05:00
Rich Harris
bea9b7965a update package-lock 2018-01-04 17:13:17 -05:00
16 changed files with 4976 additions and 364 deletions

View File

@@ -3,6 +3,7 @@ sudo: false
language: node_js language: node_js
node_js: node_js:
- "6"
- "stable" - "stable"
env: env:

View File

@@ -1,5 +1,13 @@
# sapper changelog # sapper changelog
## 0.4.0
* `%sapper.main%` has been replaced with `%sapper.scripts%` ([#86](https://github.com/sveltejs/sapper/issues/86))
* Node 6 support ([#67](https://github.com/sveltejs/sapper/pull/67))
* Explicitly load css-loader and style-loader ([#72](https://github.com/sveltejs/sapper/pull/72))
* DELETE requests are handled with `del` exports ([#77](https://github.com/sveltejs/sapper/issues/77))
* Send preloaded data for first route to client, where possible ([#3](https://github.com/sveltejs/sapper/issues/3))
## 0.3.2 ## 0.3.2
* Expose `prefetch` function ([#61](https://github.com/sveltejs/sapper/pull/61)) * Expose `prefetch` function ([#61](https://github.com/sveltejs/sapper/pull/61))

View File

@@ -1,5 +1,6 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const serialize = require('serialize-javascript');
const route_manager = require('./route_manager.js'); const route_manager = require('./route_manager.js');
const templates = require('./templates.js'); const templates = require('./templates.js');
const create_app = require('./utils/create_app.js'); const create_app = require('./utils/create_app.js');
@@ -23,9 +24,11 @@ function connect_dev() {
heartbeat: 10 * 1000 heartbeat: 10 * 1000
}), }),
async (req, res, next) => { (req, res, next) => {
asset_cache = await watcher.ready; watcher.ready.then(cache => {
next(); asset_cache = cache;
next();
});
}, },
set_req_pathname, set_req_pathname,
@@ -125,76 +128,98 @@ function get_asset_handler(opts) {
}; };
} }
function get_route_handler(fn) { const resolved = Promise.resolve();
return async function handle_route(req, res, next) {
const url = req.pathname;
const { client, server } = fn(); function get_route_handler(fn) {
function handle_route(route, req, res, next, { client, server }) {
req.params = route.exec(req.pathname);
const mod = require(server.entry)[route.id];
if (route.type === 'page') {
// preload main.js and current route
// TODO detect other stuff we can preload? images, CSS, fonts?
res.set('Link', `<${client.main_file}>;rel="preload";as="script", <${client.routes[route.id]}>;rel="preload";as="script"`);
const data = { params: req.params, query: req.query };
if (mod.preload) {
const promise = Promise.resolve(mod.preload(req)).then(preloaded => {
const serialized = try_serialize(preloaded);
Object.assign(data, preloaded);
return { rendered: mod.render(data), serialized };
});
return templates.stream(res, 200, {
scripts: promise.then(({ serialized }) => {
const main = `<script src='${client.main_file}'></script>`;
if (serialized) {
return `<script>__SAPPER__ = { preloaded: ${serialized} };</script>${main}`;
}
return main;
}),
html: promise.then(({ rendered }) => rendered.html),
head: promise.then(({ rendered }) => `<noscript id='sapper-head-start'></noscript>${rendered.head}<noscript id='sapper-head-end'></noscript>`),
styles: promise.then(({ rendered }) => (rendered.css && rendered.css.code ? `<style>${rendered.css.code}</style>` : ''))
});
} else {
const { html, head, css } = mod.render(data);
const page = templates.render(200, {
scripts: `<script src='${client.main_file}'></script>`,
html,
head: `<noscript id='sapper-head-start'></noscript>${head}<noscript id='sapper-head-end'></noscript>`,
styles: (css && css.code ? `<style>${css.code}</style>` : '')
});
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 // whatever happens, we're going to serve some HTML
res.set({ res.set({
'Content-Type': 'text/html' 'Content-Type': 'text/html'
}); });
try { resolved
for (const route of route_manager.routes) { .then(() => {
if (route.test(url)) { for (const route of route_manager.routes) {
req.params = route.exec(url); if (route.test(url)) return handle_route(route, req, res, next, fn());
const mod = require(server.entry)[route.id];
if (route.type === 'page') {
// preload main.js and current route
// TODO detect other stuff we can preload? images, CSS, fonts?
res.set('Link', `<${client.main_file}>;rel="preload";as="script", <${client.routes[route.id]}>;rel="preload";as="script"`);
const data = { params: req.params, query: req.query };
if (mod.preload) {
const promise = Promise.resolve(mod.preload(req)).then(preloaded => {
Object.assign(data, preloaded);
return mod.render(data);
});
await templates.stream(res, 200, {
main: client.main_file,
html: promise.then(rendered => rendered.html),
head: promise.then(({ head }) => `<noscript id='sapper-head-start'></noscript>${head}<noscript id='sapper-head-end'></noscript>`),
styles: promise.then(({ css }) => (css && css.code ? `<style>${css.code}</style>` : ''))
});
} else {
const { html, head, css } = mod.render(data);
const page = templates.render(200, {
main: client.main_file,
html,
head: `<noscript id='sapper-head-start'></noscript>${head}<noscript id='sapper-head-end'></noscript>`,
styles: (css && css.code ? `<style>${css.code}</style>` : '')
});
res.end(page);
}
}
else {
const handler = mod[req.method.toLowerCase()];
if (handler) handler(req, res, next);
}
return;
} }
}
next(); // no matching route — 404
} catch(err) { next();
res.status(500); })
res.end(templates.render(500, { .catch(err => {
title: (err && err.name) || 'Internal server error', res.status(500);
url, res.end(templates.render(500, {
error: escape_html(err && (err.details || err.message || err) || 'Unknown error'), title: (err && err.name) || 'Internal server error',
stack: err && err.stack.split('\n').slice(1).join('\n') url,
})); error: escape_html(err && (err.details || err.message || err) || 'Unknown error'),
} stack: err && err.stack.split('\n').slice(1).join('\n')
}));
});
}; };
} }
@@ -207,7 +232,7 @@ function get_not_found_handler(fn) {
title: 'Not found', title: 'Not found',
status: 404, status: 404,
method: req.method, method: req.method,
main: asset_cache.client.main_file, scripts: `<script src='${asset_cache.client.main_file}'></script>`,
url: req.url url: req.url
})); }));
}; };
@@ -236,3 +261,11 @@ function compose_handlers(handlers) {
function read_json(file) { function read_json(file) {
return JSON.parse(fs.readFileSync(file, 'utf-8')); return JSON.parse(fs.readFileSync(file, 'utf-8'));
} }
function try_serialize(data) {
try {
return serialize(data);
} catch (err) {
return null;
}
}

View File

@@ -1,10 +1,22 @@
const fs = require('fs'); const fs = require('fs');
const glob = require('glob'); const glob = require('glob');
const chalk = require('chalk');
const chokidar = require('chokidar'); const chokidar = require('chokidar');
const framer = require('code-frame');
const { locate } = require('locate-character');
const { dev } = require('./config.js'); const { dev } = require('./config.js');
let templates; let templates;
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() { function create_templates() {
templates = glob.sync('*.html', { cwd: 'templates' }) templates = glob.sync('*.html', { cwd: 'templates' })
.map(file => { .map(file => {
@@ -12,7 +24,24 @@ function create_templates() {
const status = file.replace('.html', '').toLowerCase(); const status = file.replace('.html', '').toLowerCase();
if (!/^[0-9x]{3}$/.test(status)) { if (!/^[0-9x]{3}$/.test(status)) {
throw new Error(`Bad template — should be a valid status code like 404.html, or a wildcard like 2xx.html`); 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 } = locate(template, index, { offsetLine: 1 });
const frame = framer(template, line, column);
error({
title: `templates/${file}`,
body: `<script src='%sapper.main%'> is unsupported — use %sapper.scripts% (without the <script> tag) instead`,
url: 'https://github.com/sveltejs/sapper/issues/86',
frame
});
} }
const specificity = ( const specificity = (
@@ -31,10 +60,14 @@ function create_templates() {
return key in data ? data[key] : ''; return key in data ? data[key] : '';
}); });
}, },
stream: async (res, data) => { stream: (res, data) => {
let i = 0; let i = 0;
do { function stream_inner() {
if (i >= template.length) {
return;
}
const start = template.indexOf('%sapper', i); const start = template.indexOf('%sapper', i);
if (start === -1) { if (start === -1) {
@@ -53,9 +86,14 @@ function create_templates() {
const match = /sapper\.(\w+)/.exec(tag); const match = /sapper\.(\w+)/.exec(tag);
if (!match || !(match[1] in data)) throw new Error(`Bad template`); // TODO ditto if (!match || !(match[1] in data)) throw new Error(`Bad template`); // TODO ditto
res.write(await data[match[1]]); return Promise.resolve(data[match[1]]).then(datamatch => {
i = end + 1; res.write(datamatch);
} while (i < template.length); i = end + 1;
return stream_inner();
});
}
return Promise.resolve().then(stream_inner);
} }
}; };
}) })

344
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "sapper", "name": "sapper",
"version": "0.2.10", "version": "0.3.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -2114,12 +2114,14 @@
"dependencies": { "dependencies": {
"abbrev": { "abbrev": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
"integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=",
"optional": true "optional": true
}, },
"ajv": { "ajv": {
"version": "4.11.8", "version": "4.11.8",
"bundled": true, "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
"optional": true, "optional": true,
"requires": { "requires": {
"co": "4.6.0", "co": "4.6.0",
@@ -2128,16 +2130,19 @@
}, },
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
}, },
"aproba": { "aproba": {
"version": "1.1.1", "version": "1.1.1",
"bundled": true, "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz",
"integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=",
"optional": true "optional": true
}, },
"are-we-there-yet": { "are-we-there-yet": {
"version": "1.1.4", "version": "1.1.4",
"bundled": true, "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
"optional": true, "optional": true,
"requires": { "requires": {
"delegates": "1.0.0", "delegates": "1.0.0",
@@ -2146,36 +2151,43 @@
}, },
"asn1": { "asn1": {
"version": "0.2.3", "version": "0.2.3",
"bundled": true, "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
"optional": true "optional": true
}, },
"assert-plus": { "assert-plus": {
"version": "0.2.0", "version": "0.2.0",
"bundled": true, "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
"optional": true "optional": true
}, },
"asynckit": { "asynckit": {
"version": "0.4.0", "version": "0.4.0",
"bundled": true, "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"optional": true "optional": true
}, },
"aws-sign2": { "aws-sign2": {
"version": "0.6.0", "version": "0.6.0",
"bundled": true, "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
"optional": true "optional": true
}, },
"aws4": { "aws4": {
"version": "1.6.0", "version": "1.6.0",
"bundled": true, "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
"optional": true "optional": true
}, },
"balanced-match": { "balanced-match": {
"version": "0.4.2", "version": "0.4.2",
"bundled": true "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
}, },
"bcrypt-pbkdf": { "bcrypt-pbkdf": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true, "optional": true,
"requires": { "requires": {
"tweetnacl": "0.14.5" "tweetnacl": "0.14.5"
@@ -2183,21 +2195,24 @@
}, },
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
"bundled": true, "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"requires": { "requires": {
"inherits": "2.0.3" "inherits": "2.0.3"
} }
}, },
"boom": { "boom": {
"version": "2.10.1", "version": "2.10.1",
"bundled": true, "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
"requires": { "requires": {
"hoek": "2.16.3" "hoek": "2.16.3"
} }
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.7", "version": "1.1.7",
"bundled": true, "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
"integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=",
"requires": { "requires": {
"balanced-match": "0.4.2", "balanced-match": "0.4.2",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@@ -2205,51 +2220,61 @@
}, },
"buffer-shims": { "buffer-shims": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
"integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
}, },
"caseless": { "caseless": {
"version": "0.12.0", "version": "0.12.0",
"bundled": true, "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"optional": true "optional": true
}, },
"co": { "co": {
"version": "4.6.0", "version": "4.6.0",
"bundled": true, "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"optional": true "optional": true
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
}, },
"combined-stream": { "combined-stream": {
"version": "1.0.5", "version": "1.0.5",
"bundled": true, "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
"requires": { "requires": {
"delayed-stream": "1.0.0" "delayed-stream": "1.0.0"
} }
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
}, },
"cryptiles": { "cryptiles": {
"version": "2.0.5", "version": "2.0.5",
"bundled": true, "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
"requires": { "requires": {
"boom": "2.10.1" "boom": "2.10.1"
} }
}, },
"dashdash": { "dashdash": {
"version": "1.14.1", "version": "1.14.1",
"bundled": true, "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"optional": true, "optional": true,
"requires": { "requires": {
"assert-plus": "1.0.0" "assert-plus": "1.0.0"
@@ -2257,14 +2282,16 @@
"dependencies": { "dependencies": {
"assert-plus": { "assert-plus": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"optional": true "optional": true
} }
} }
}, },
"debug": { "debug": {
"version": "2.6.8", "version": "2.6.8",
"bundled": true, "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
"optional": true, "optional": true,
"requires": { "requires": {
"ms": "2.0.0" "ms": "2.0.0"
@@ -2272,26 +2299,31 @@
}, },
"deep-extend": { "deep-extend": {
"version": "0.4.2", "version": "0.4.2",
"bundled": true, "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=",
"optional": true "optional": true
}, },
"delayed-stream": { "delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
}, },
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"optional": true "optional": true
}, },
"detect-libc": { "detect-libc": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz",
"integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=",
"optional": true "optional": true
}, },
"ecc-jsbn": { "ecc-jsbn": {
"version": "0.1.1", "version": "0.1.1",
"bundled": true, "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true, "optional": true,
"requires": { "requires": {
"jsbn": "0.1.1" "jsbn": "0.1.1"
@@ -2299,21 +2331,25 @@
}, },
"extend": { "extend": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
"optional": true "optional": true
}, },
"extsprintf": { "extsprintf": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
"integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA="
}, },
"forever-agent": { "forever-agent": {
"version": "0.6.1", "version": "0.6.1",
"bundled": true, "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
"optional": true "optional": true
}, },
"form-data": { "form-data": {
"version": "2.1.4", "version": "2.1.4",
"bundled": true, "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
"integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
"optional": true, "optional": true,
"requires": { "requires": {
"asynckit": "0.4.0", "asynckit": "0.4.0",
@@ -2323,11 +2359,13 @@
}, },
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
}, },
"fstream": { "fstream": {
"version": "1.0.11", "version": "1.0.11",
"bundled": true, "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
"requires": { "requires": {
"graceful-fs": "4.1.11", "graceful-fs": "4.1.11",
"inherits": "2.0.3", "inherits": "2.0.3",
@@ -2337,7 +2375,8 @@
}, },
"fstream-ignore": { "fstream-ignore": {
"version": "1.0.5", "version": "1.0.5",
"bundled": true, "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
"integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=",
"optional": true, "optional": true,
"requires": { "requires": {
"fstream": "1.0.11", "fstream": "1.0.11",
@@ -2347,7 +2386,8 @@
}, },
"gauge": { "gauge": {
"version": "2.7.4", "version": "2.7.4",
"bundled": true, "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"optional": true, "optional": true,
"requires": { "requires": {
"aproba": "1.1.1", "aproba": "1.1.1",
@@ -2362,7 +2402,8 @@
}, },
"getpass": { "getpass": {
"version": "0.1.7", "version": "0.1.7",
"bundled": true, "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"optional": true, "optional": true,
"requires": { "requires": {
"assert-plus": "1.0.0" "assert-plus": "1.0.0"
@@ -2370,14 +2411,16 @@
"dependencies": { "dependencies": {
"assert-plus": { "assert-plus": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"optional": true "optional": true
} }
} }
}, },
"glob": { "glob": {
"version": "7.1.2", "version": "7.1.2",
"bundled": true, "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"requires": { "requires": {
"fs.realpath": "1.0.0", "fs.realpath": "1.0.0",
"inflight": "1.0.6", "inflight": "1.0.6",
@@ -2389,16 +2432,19 @@
}, },
"graceful-fs": { "graceful-fs": {
"version": "4.1.11", "version": "4.1.11",
"bundled": true "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
}, },
"har-schema": { "har-schema": {
"version": "1.0.5", "version": "1.0.5",
"bundled": true, "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
"integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
"optional": true "optional": true
}, },
"har-validator": { "har-validator": {
"version": "4.2.1", "version": "4.2.1",
"bundled": true, "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
"integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
"optional": true, "optional": true,
"requires": { "requires": {
"ajv": "4.11.8", "ajv": "4.11.8",
@@ -2407,12 +2453,14 @@
}, },
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"optional": true "optional": true
}, },
"hawk": { "hawk": {
"version": "3.1.3", "version": "3.1.3",
"bundled": true, "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
"requires": { "requires": {
"boom": "2.10.1", "boom": "2.10.1",
"cryptiles": "2.0.5", "cryptiles": "2.0.5",
@@ -2422,11 +2470,13 @@
}, },
"hoek": { "hoek": {
"version": "2.16.3", "version": "2.16.3",
"bundled": true "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
}, },
"http-signature": { "http-signature": {
"version": "1.1.1", "version": "1.1.1",
"bundled": true, "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
"optional": true, "optional": true,
"requires": { "requires": {
"assert-plus": "0.2.0", "assert-plus": "0.2.0",
@@ -2436,7 +2486,8 @@
}, },
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
"bundled": true, "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": { "requires": {
"once": "1.4.0", "once": "1.4.0",
"wrappy": "1.0.2" "wrappy": "1.0.2"
@@ -2444,37 +2495,44 @@
}, },
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": { "ini": {
"version": "1.3.4", "version": "1.3.4",
"bundled": true, "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
"optional": true "optional": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"requires": { "requires": {
"number-is-nan": "1.0.1" "number-is-nan": "1.0.1"
} }
}, },
"is-typedarray": { "is-typedarray": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"optional": true "optional": true
}, },
"isarray": { "isarray": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
}, },
"isstream": { "isstream": {
"version": "0.1.2", "version": "0.1.2",
"bundled": true, "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"optional": true "optional": true
}, },
"jodid25519": { "jodid25519": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz",
"integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=",
"optional": true, "optional": true,
"requires": { "requires": {
"jsbn": "0.1.1" "jsbn": "0.1.1"
@@ -2482,17 +2540,20 @@
}, },
"jsbn": { "jsbn": {
"version": "0.1.1", "version": "0.1.1",
"bundled": true, "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true "optional": true
}, },
"json-schema": { "json-schema": {
"version": "0.2.3", "version": "0.2.3",
"bundled": true, "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
"optional": true "optional": true
}, },
"json-stable-stringify": { "json-stable-stringify": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
"optional": true, "optional": true,
"requires": { "requires": {
"jsonify": "0.0.0" "jsonify": "0.0.0"
@@ -2500,17 +2561,20 @@
}, },
"json-stringify-safe": { "json-stringify-safe": {
"version": "5.0.1", "version": "5.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"optional": true "optional": true
}, },
"jsonify": { "jsonify": {
"version": "0.0.0", "version": "0.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"optional": true "optional": true
}, },
"jsprim": { "jsprim": {
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz",
"integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=",
"optional": true, "optional": true,
"requires": { "requires": {
"assert-plus": "1.0.0", "assert-plus": "1.0.0",
@@ -2521,48 +2585,56 @@
"dependencies": { "dependencies": {
"assert-plus": { "assert-plus": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"optional": true "optional": true
} }
} }
}, },
"mime-db": { "mime-db": {
"version": "1.27.0", "version": "1.27.0",
"bundled": true "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
"integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE="
}, },
"mime-types": { "mime-types": {
"version": "2.1.15", "version": "2.1.15",
"bundled": true, "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
"integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=",
"requires": { "requires": {
"mime-db": "1.27.0" "mime-db": "1.27.0"
} }
}, },
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": { "requires": {
"brace-expansion": "1.1.7" "brace-expansion": "1.1.7"
} }
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
}, },
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"optional": true "optional": true
}, },
"node-pre-gyp": { "node-pre-gyp": {
"version": "0.6.39", "version": "0.6.39",
"bundled": true, "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz",
"integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==",
"optional": true, "optional": true,
"requires": { "requires": {
"detect-libc": "1.0.2", "detect-libc": "1.0.2",
@@ -2580,7 +2652,8 @@
}, },
"nopt": { "nopt": {
"version": "4.0.1", "version": "4.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"optional": true, "optional": true,
"requires": { "requires": {
"abbrev": "1.1.0", "abbrev": "1.1.0",
@@ -2589,7 +2662,8 @@
}, },
"npmlog": { "npmlog": {
"version": "4.1.0", "version": "4.1.0",
"bundled": true, "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz",
"integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==",
"optional": true, "optional": true,
"requires": { "requires": {
"are-we-there-yet": "1.1.4", "are-we-there-yet": "1.1.4",
@@ -2600,38 +2674,45 @@
}, },
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
}, },
"oauth-sign": { "oauth-sign": {
"version": "0.8.2", "version": "0.8.2",
"bundled": true, "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
"optional": true "optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
"bundled": true, "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"optional": true "optional": true
}, },
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": { "requires": {
"wrappy": "1.0.2" "wrappy": "1.0.2"
} }
}, },
"os-homedir": { "os-homedir": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"optional": true "optional": true
}, },
"os-tmpdir": { "os-tmpdir": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"optional": true "optional": true
}, },
"osenv": { "osenv": {
"version": "0.1.4", "version": "0.1.4",
"bundled": true, "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
"integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
"optional": true, "optional": true,
"requires": { "requires": {
"os-homedir": "1.0.2", "os-homedir": "1.0.2",
@@ -2640,30 +2721,36 @@
}, },
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
}, },
"performance-now": { "performance-now": {
"version": "0.2.0", "version": "0.2.0",
"bundled": true, "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
"integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
"optional": true "optional": true
}, },
"process-nextick-args": { "process-nextick-args": {
"version": "1.0.7", "version": "1.0.7",
"bundled": true "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
}, },
"punycode": { "punycode": {
"version": "1.4.1", "version": "1.4.1",
"bundled": true, "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
"optional": true "optional": true
}, },
"qs": { "qs": {
"version": "6.4.0", "version": "6.4.0",
"bundled": true, "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
"optional": true "optional": true
}, },
"rc": { "rc": {
"version": "1.2.1", "version": "1.2.1",
"bundled": true, "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
"integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
"optional": true, "optional": true,
"requires": { "requires": {
"deep-extend": "0.4.2", "deep-extend": "0.4.2",
@@ -2674,14 +2761,16 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"bundled": true, "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"optional": true "optional": true
} }
} }
}, },
"readable-stream": { "readable-stream": {
"version": "2.2.9", "version": "2.2.9",
"bundled": true, "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz",
"integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=",
"requires": { "requires": {
"buffer-shims": "1.0.0", "buffer-shims": "1.0.0",
"core-util-is": "1.0.2", "core-util-is": "1.0.2",
@@ -2694,7 +2783,8 @@
}, },
"request": { "request": {
"version": "2.81.0", "version": "2.81.0",
"bundled": true, "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
"integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
"optional": true, "optional": true,
"requires": { "requires": {
"aws-sign2": "0.6.0", "aws-sign2": "0.6.0",
@@ -2723,40 +2813,47 @@
}, },
"rimraf": { "rimraf": {
"version": "2.6.1", "version": "2.6.1",
"bundled": true, "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
"integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
"requires": { "requires": {
"glob": "7.1.2" "glob": "7.1.2"
} }
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.0.1", "version": "5.0.1",
"bundled": true "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz",
"integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c="
}, },
"semver": { "semver": {
"version": "5.3.0", "version": "5.3.0",
"bundled": true, "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
"optional": true "optional": true
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"optional": true "optional": true
}, },
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"optional": true "optional": true
}, },
"sntp": { "sntp": {
"version": "1.0.9", "version": "1.0.9",
"bundled": true, "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
"requires": { "requires": {
"hoek": "2.16.3" "hoek": "2.16.3"
} }
}, },
"sshpk": { "sshpk": {
"version": "1.13.0", "version": "1.13.0",
"bundled": true, "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz",
"integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=",
"optional": true, "optional": true,
"requires": { "requires": {
"asn1": "0.2.3", "asn1": "0.2.3",
@@ -2772,14 +2869,16 @@
"dependencies": { "dependencies": {
"assert-plus": { "assert-plus": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"optional": true "optional": true
} }
} }
}, },
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"requires": { "requires": {
"code-point-at": "1.1.0", "code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0", "is-fullwidth-code-point": "1.0.0",
@@ -2788,31 +2887,36 @@
}, },
"string_decoder": { "string_decoder": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz",
"integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=",
"requires": { "requires": {
"safe-buffer": "5.0.1" "safe-buffer": "5.0.1"
} }
}, },
"stringstream": { "stringstream": {
"version": "0.0.5", "version": "0.0.5",
"bundled": true, "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
"optional": true "optional": true
}, },
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": { "requires": {
"ansi-regex": "2.1.1" "ansi-regex": "2.1.1"
} }
}, },
"strip-json-comments": { "strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"optional": true "optional": true
}, },
"tar": { "tar": {
"version": "2.2.1", "version": "2.2.1",
"bundled": true, "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
"requires": { "requires": {
"block-stream": "0.0.9", "block-stream": "0.0.9",
"fstream": "1.0.11", "fstream": "1.0.11",
@@ -2821,7 +2925,8 @@
}, },
"tar-pack": { "tar-pack": {
"version": "3.4.0", "version": "3.4.0",
"bundled": true, "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz",
"integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=",
"optional": true, "optional": true,
"requires": { "requires": {
"debug": "2.6.8", "debug": "2.6.8",
@@ -2836,7 +2941,8 @@
}, },
"tough-cookie": { "tough-cookie": {
"version": "2.3.2", "version": "2.3.2",
"bundled": true, "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
"integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
"optional": true, "optional": true,
"requires": { "requires": {
"punycode": "1.4.1" "punycode": "1.4.1"
@@ -2844,7 +2950,8 @@
}, },
"tunnel-agent": { "tunnel-agent": {
"version": "0.6.0", "version": "0.6.0",
"bundled": true, "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"optional": true, "optional": true,
"requires": { "requires": {
"safe-buffer": "5.0.1" "safe-buffer": "5.0.1"
@@ -2852,26 +2959,31 @@
}, },
"tweetnacl": { "tweetnacl": {
"version": "0.14.5", "version": "0.14.5",
"bundled": true, "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true "optional": true
}, },
"uid-number": { "uid-number": {
"version": "0.0.6", "version": "0.0.6",
"bundled": true, "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
"integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=",
"optional": true "optional": true
}, },
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
}, },
"uuid": { "uuid": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
"integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=",
"optional": true "optional": true
}, },
"verror": { "verror": {
"version": "1.3.6", "version": "1.3.6",
"bundled": true, "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
"integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=",
"optional": true, "optional": true,
"requires": { "requires": {
"extsprintf": "1.0.2" "extsprintf": "1.0.2"
@@ -2879,7 +2991,8 @@
}, },
"wide-align": { "wide-align": {
"version": "1.1.2", "version": "1.1.2",
"bundled": true, "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"optional": true, "optional": true,
"requires": { "requires": {
"string-width": "1.0.2" "string-width": "1.0.2"
@@ -2887,7 +3000,8 @@
}, },
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
} }
} }
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "sapper", "name": "sapper",
"version": "0.3.2", "version": "0.4.0",
"description": "Military-grade apps, engineered by Svelte", "description": "Military-grade apps, engineered by Svelte",
"main": "lib/index.js", "main": "lib/index.js",
"bin": { "bin": {
@@ -19,11 +19,14 @@
"dependencies": { "dependencies": {
"chalk": "^2.3.0", "chalk": "^2.3.0",
"chokidar": "^1.7.0", "chokidar": "^1.7.0",
"code-frame": "^5.0.0",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"locate-character": "^2.0.5",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"relative": "^3.0.2", "relative": "^3.0.2",
"require-relative": "^0.8.7", "require-relative": "^0.8.7",
"rimraf": "^2.6.2", "rimraf": "^2.6.2",
"serialize-javascript": "^1.4.0",
"webpack": "^3.10.0", "webpack": "^3.10.0",
"webpack-hot-middleware": "^2.21.0" "webpack-hot-middleware": "^2.21.0"
}, },

View File

@@ -68,10 +68,16 @@ function render(Component: ComponentConstructor, data: any, scroll: ScrollPositi
} }
} }
function prepare_route(Component, data) { function prepare_route(Component: ComponentConstructor, data: RouteData) {
return Promise.resolve( if (!Component.preload) {
Component.preload ? Component.preload(data) : {} return { Component, data };
).then(preloaded => { }
if (!component && window.__SAPPER__ && window.__SAPPER__.preloaded) {
return { Component, data: Object.assign(data, window.__SAPPER__.preloaded) };
}
return Promise.resolve(Component.preload(data)).then(preloaded => {
Object.assign(data, preloaded) Object.assign(data, preloaded)
return { Component, data }; return { Component, data };
}); });
@@ -176,10 +182,10 @@ export function prefetch(href: string) {
} }
function handle_touchstart_mouseover(event: MouseEvent | TouchEvent) { function handle_touchstart_mouseover(event: MouseEvent | TouchEvent) {
const a: HTMLAnchorElement = <HTMLAnchorElement>findAnchor(<Node>event.target); const a: HTMLAnchorElement = <HTMLAnchorElement>findAnchor(<Node>event.target);
if (!a || a.rel !== 'prefetch') return; if (!a || a.rel !== 'prefetch') return;
prefetch(a.href); prefetch(a.href);
} }
let inited: boolean; let inited: boolean;

View File

@@ -2722,9 +2722,9 @@
"integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ="
}, },
"marked": { "marked": {
"version": "0.3.7", "version": "0.3.9",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.7.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz",
"integrity": "sha512-zBEP4qO1YQp5aXHt8S5wTiOv9i2X74V/LQL0zhUNvVaklt6Ywa6lChxIvS+ibYlCGgADwKwZFhjC3+XfpsvQvQ==" "integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw=="
}, },
"math-expression-evaluator": { "math-expression-evaluator": {
"version": "1.2.17", "version": "1.2.17",

View File

@@ -15,7 +15,7 @@
"express": "^4.16.2", "express": "^4.16.2",
"extract-text-webpack-plugin": "^3.0.2", "extract-text-webpack-plugin": "^3.0.2",
"glob": "^7.1.2", "glob": "^7.1.2",
"marked": "^0.3.7", "marked": "^0.3.9",
"node-fetch": "^1.7.3", "node-fetch": "^1.7.3",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"serve-static": "^1.13.1", "serve-static": "^1.13.1",

View File

@@ -0,0 +1,9 @@
export function del(req, res) {
res.set({
'Content-Type': 'application/json'
});
res.end(JSON.stringify({
id: req.params.id
}));
}

View File

@@ -0,0 +1,15 @@
<button class='del' on:click='del()'>delete</button>
<script>
export default {
methods: {
del() {
fetch(`/api/delete/42`, { method: 'DELETE' })
.then(r => r.json())
.then(data => {
window.deleted = data;
});
}
}
};
</script>

View File

@@ -3,7 +3,7 @@
<script> <script>
export default { export default {
preload({ url }) { preload({ url }) {
return { url }; if (url) return { url };
} }
}; };
</script> </script>

View File

@@ -32,6 +32,6 @@
<!-- Sapper creates a <script> tag containing `templates/main.js` <!-- Sapper creates a <script> tag containing `templates/main.js`
and anything else it needs to hydrate the app and and anything else it needs to hydrate the app and
initialise the router --> initialise the router -->
<script src='%sapper.main%'></script> %sapper.scripts%
</body> </body>
</html> </html>

View File

@@ -9,6 +9,12 @@ const fetch = require('node-fetch');
run('production'); run('production');
run('development'); run('development');
Nightmare.action('page', {
title(done) {
this.evaluate_now(() => document.querySelector('h1').textContent, done);
}
});
function run(env) { function run(env) {
describe(`env=${env}`, function () { describe(`env=${env}`, function () {
this.timeout(20000); this.timeout(20000);
@@ -62,52 +68,60 @@ function run(env) {
}); });
} }
before(async () => { before(() => {
process.chdir(path.resolve(__dirname, '../app')); process.chdir(path.resolve(__dirname, '../app'));
process.env.NODE_ENV = env; process.env.NODE_ENV = env;
let exec_promise = Promise.resolve();
let sapper;
if (env === 'production') { if (env === 'production') {
const cli = path.resolve(__dirname, '../../cli/index.js'); const cli = path.resolve(__dirname, '../../cli/index.js');
await exec(`${cli} build`); exec_promise = exec(`${cli} build`);
} }
const resolved = require.resolve('../..'); return exec_promise.then(() => {
delete require.cache[resolved]; const resolved = require.resolve('../..');
const sapper = require(resolved); delete require.cache[resolved];
sapper = require(resolved);
PORT = await getPort(); return getPort();
base = `http://localhost:${PORT}`; }).then(port => {
PORT = port;
base = `http://localhost:${PORT}`;
global.fetch = (url, opts) => { global.fetch = (url, opts) => {
if (url[0] === '/') url = `${base}${url}`; if (url[0] === '/') url = `${base}${url}`;
return fetch(url, opts); return fetch(url, opts);
}; };
let captured; let captured;
capture = async fn => { capture = fn => {
const result = captured = []; const result = captured = [];
await fn(); return fn().then(() => {
captured = null; captured = null;
return result; return result;
}; });
};
const app = express(); const app = express();
app.use(serve('assets')); app.use(serve('assets'));
app.use((req, res, next) => { app.use((req, res, next) => {
if (captured) captured.push(req); if (captured) captured.push(req);
next(); next();
}); });
middleware = sapper(); middleware = sapper();
app.use(middleware); app.use(middleware);
return new Promise((fulfil, reject) => { return new Promise((fulfil, reject) => {
server = app.listen(PORT, err => { server = app.listen(PORT, err => {
if (err) reject(err); if (err) reject(err);
else fulfil(); else fulfil();
});
}); });
}); });
}); });
@@ -137,173 +151,165 @@ function run(env) {
}); });
}); });
afterEach(async () => { afterEach(() => {
await nightmare.end(); return nightmare.end();
}); });
it('serves /', async () => { it('serves /', () => {
const title = await nightmare return nightmare.goto(base).page.title().then(title => {
.goto(base) assert.equal(title, 'Great success!');
.evaluate(() => document.querySelector('h1').textContent);
assert.equal(title, 'Great success!');
});
it('serves static route', async () => {
const title = await nightmare
.goto(`${base}/about`)
.evaluate(() => document.querySelector('h1').textContent);
assert.equal(title, 'About this site');
});
it('serves dynamic route', async () => {
const title = await nightmare
.goto(`${base}/blog/what-is-sapper`)
.evaluate(() => document.querySelector('h1').textContent);
assert.equal(title, 'What is Sapper?');
});
it('navigates to a new page without reloading', async () => {
await nightmare.goto(base).wait(() => window.READY).wait(200);
const requests = await capture(async () => {
await nightmare.click('a[href="/about"]');
}); });
assert.equal(
await nightmare.path(),
'/about'
);
assert.equal(
await nightmare.evaluate(() => document.title),
'About'
);
assert.deepEqual(requests.map(r => r.url), []);
}); });
it('navigates programmatically', async () => { it('serves static route', () => {
await nightmare return nightmare.goto(`${base}/about`).page.title().then(title => {
assert.equal(title, 'About this site');
});
});
it('serves dynamic route', () => {
return nightmare.goto(`${base}/blog/what-is-sapper`).page.title().then(title => {
assert.equal(title, 'What is Sapper?');
});
});
it('navigates to a new page without reloading', () => {
return nightmare.goto(base).wait(() => window.READY).wait(200)
.then(() => {
return capture(() => nightmare.click('a[href="/about"]'));
})
.then(requests => {
assert.deepEqual(requests.map(r => r.url), []);
return nightmare.path();
})
.then(path => {
assert.equal(path, '/about');
return nightmare.title();
})
.then(title => {
assert.equal(title, 'About');
});
});
it('navigates programmatically', () => {
return nightmare
.goto(`${base}/about`) .goto(`${base}/about`)
.wait(() => window.READY) .wait(() => window.READY)
.click('.goto') .click('.goto')
.wait(() => window.location.pathname === '/blog/what-is-sapper') .wait(() => window.location.pathname === '/blog/what-is-sapper')
.wait(100); .wait(100)
.title()
assert.equal( .then(title => {
await nightmare.evaluate(() => document.title), assert.equal(title, 'What is Sapper?');
'What is Sapper?' });
);
}); });
it('prefetches programmatically', async () => { it('prefetches programmatically', () => {
await nightmare return nightmare
.goto(`${base}/about`) .goto(`${base}/about`)
.wait(() => window.READY); .wait(() => window.READY)
.then(() => {
const requests = await capture(async () => { return capture(() => {
return await nightmare return nightmare
.click('.prefetch') .click('.prefetch')
.wait(100); .wait(100);
}); });
})
assert.ok(!!requests.find(r => r.url === '/api/blog/why-the-name')); .then(requests => {
assert.ok(!!requests.find(r => r.url === '/api/blog/why-the-name'));
});
}); });
it('scrolls to active deeplink', async () => { it('scrolls to active deeplink', () => {
const scrollY = await nightmare return nightmare
.goto(`${base}/blog/a-very-long-post#four`) .goto(`${base}/blog/a-very-long-post#four`)
.wait(() => window.READY) .wait(() => window.READY)
.wait(100) .wait(100)
.evaluate(() => window.scrollY); .evaluate(() => window.scrollY)
.then(scrollY => {
assert.ok(scrollY > 0, scrollY); assert.ok(scrollY > 0, scrollY);
});
}); });
it('reuses prefetch promise', async () => { it('reuses prefetch promise', () => {
await nightmare return nightmare
.goto(`${base}/blog`) .goto(`${base}/blog`)
.wait(() => window.READY) .wait(() => window.READY)
.wait(200); .wait(200)
.then(() => {
return capture(() => {
return nightmare
.mouseover('[href="/blog/what-is-sapper"]')
.wait(200);
});
})
.then(mouseover_requests => {
assert.deepEqual(mouseover_requests.map(r => r.url), [
'/api/blog/what-is-sapper'
]);
const mouseover_requests = (await capture(async () => { return capture(() => {
await nightmare return nightmare
.mouseover('[href="/blog/what-is-sapper"]') .click('[href="/blog/what-is-sapper"]')
.wait(200); .wait(200);
})).map(r => r.url); });
})
assert.deepEqual(mouseover_requests, [ .then(click_requests => {
'/api/blog/what-is-sapper' assert.deepEqual(click_requests.map(r => r.url), []);
]); });
const click_requests = (await capture(async () => {
await nightmare
.click('[href="/blog/what-is-sapper"]')
.wait(200);
})).map(r => r.url);
assert.deepEqual(click_requests, []);
}); });
it('cancels navigation if subsequent navigation occurs during preload', async () => { it('cancels navigation if subsequent navigation occurs during preload', () => {
await nightmare return nightmare
.goto(base) .goto(base)
.wait(() => window.READY) .wait(() => window.READY)
.click('a[href="/slow-preload"]') .click('a[href="/slow-preload"]')
.wait(100) .wait(100)
.click('a[href="/about"]') .click('a[href="/about"]')
.wait(100); .wait(100)
.then(() => nightmare.path())
assert.equal( .then(path => {
await nightmare.path(), assert.equal(path, '/about');
'/about' return nightmare.title();
); })
.then(title => {
assert.equal( assert.equal(title, 'About');
await nightmare.evaluate(() => document.querySelector('h1').textContent), return nightmare.evaluate(() => window.fulfil({})).wait(100);
'About this site' })
); .then(() => nightmare.path())
.then(path => {
await nightmare assert.equal(path, '/about');
.evaluate(() => window.fulfil({})) return nightmare.title();
.wait(100); })
.then(title => {
assert.equal( assert.equal(title, 'About');
await nightmare.path(), });
'/about'
);
assert.equal(
await nightmare.evaluate(() => document.querySelector('h1').textContent),
'About this site'
);
}); });
it('passes entire request object to preload', async () => { it('passes entire request object to preload', () => {
const html = await nightmare return nightmare
.goto(`${base}/show-url`) .goto(`${base}/show-url`)
.evaluate(() => document.querySelector('p').innerHTML); .wait(() => window.READY)
.evaluate(() => document.querySelector('p').innerHTML)
assert.equal(html, `URL is /show-url`); .end().then(html => {
assert.equal(html, `URL is /show-url`);
});
}); });
}); });
describe('headers', () => { describe('headers', () => {
it('sets Content-Type and Link...preload headers', async () => { it('sets Content-Type and Link...preload headers', () => {
const { headers } = await get('/'); return get('/').then(({ headers }) => {
assert.equal(
headers['Content-Type'],
'text/html'
);
assert.equal( assert.ok(
headers['Content-Type'], /<\/client\/main.\w+\.js>;rel="preload";as="script", <\/client\/_.\d+.\w+.js>;rel="preload";as="script"/.test(headers['Link']),
'text/html' headers['Link']
); );
});
assert.ok(
/<\/client\/main.\w+\.js>;rel="preload";as="script", <\/client\/_.\d+.\w+.js>;rel="preload";as="script"/.test(headers['Link']),
headers['Link']
);
}); });
}); });
}); });

View File

@@ -6,7 +6,12 @@ module.exports = {
client: { client: {
entry: () => { entry: () => {
return { return {
main: entry.client 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'
]
}; };
}, },

4374
yarn.lock Normal file

File diff suppressed because it is too large Load Diff