Merge branch 'master' into context-perf

This commit is contained in:
Kim Gardner
2018-03-20 12:01:31 -04:00
committed by GitHub
15 changed files with 667 additions and 197 deletions
+1 -1
View File
@@ -92,7 +92,7 @@ jobs:
- save_cache:
key: build-cache-{{ .Branch }}-{{ .Revision }}
paths:
- ./node_modules/.cache/hard-source
- ./node_modules/.cache/babel-loader
- persist_to_workspace:
root: .
paths: dist
@@ -25,7 +25,8 @@ class QuestionBoxBuilder extends React.Component {
async loadEditor() {
const {
default: MarkdownEditor,
} = await import('coral-framework/components/MarkdownEditor');
} = await import(/* webpackChunkName: "markdownEditor" */
'coral-framework/components/MarkdownEditor');
return this.setState({
loading: false,
+2
View File
@@ -100,6 +100,8 @@ sidebar:
children:
- title: Authentication
url: /integrating/authentication/
- title: Asset Managment
url: /integrating/asset-management/
- title: Configuring the Comment Stream
url: /integrating/configuring-comment-stream/
- title: Configuring the Admin
+2 -2
View File
@@ -251,6 +251,6 @@ export default withReaction('pride')(PrideButton);
````
And that's it! You've created your first reaction button! :rainbow:
And that's it! You've created your first reaction button! 🌈
If you would like to continue to the next part of our Plugin Tutorial, see Part 2 in the sidebar.
If you would like to continue to the next part of our Plugin Tutorial, see Customizing Plugins with Coral UI in the left sidebar.
+314
View File
@@ -0,0 +1,314 @@
---
title: Asset Management
permalink: /integrating/asset-management/
---
One of the most frequent questions that we get asked by organizations trying to
integrate Talk is: _How do we hook our CMS up to Talk so that articles are in
sync?_
This guide is designed to explain the steps to take your base installation of
Talk and configure it to allow only assets pushed into it from your CMS, and
keep your URL/title in sync. We won't cover here how to install the plugin, as
it is covered in our [Plugins Overview](/talk/plugins/).
## Why do we need to create a plugin?
By default, Talk will use "Lazy Asset Creation" to dynamically generate Assets
in Talk in order to make it easier for lighter installations. In order to have
more strict control over this flow, we will create a plugin that will:
1. Disable "Lazy Asset Creation" by [Overriding a Resolver](#Overriding-a-Resolver).
2. Create Assets from our CMS by [Creating a New Asset Route](#Creating-a-New-Asset-Route).
3. Facilitate updates from our CMS to keep Talk in sync by [Creating an Asset Update Route](#Creating-an-Asset-Update-Route).
We will then modify our embed so that we can [Target the Asset](#Target-the-Asset).
But first we should grab our basic plugin structure:
```sh
# clone our example repo (that comes with all the code below!)
git clone https://github.com/coralproject/talk-plugin-asset-manager-example.git
# checkout the step-1 tag that starts us off with the basic file structure of
# the plugin.
git checkout step-1
```
## Overriding a Resolver
First we'll replace the content of the `resolver.js` file with the following:
```js
// We'll need to modify the behavior of how assets are
// "resolved" in Talk, so we override the base asset resolver
// for the RootQuery type.
module.exports = {
RootQuery: {
asset: async (root, args, ctx) => {
// We'll grab the id of the asset being requested
// such that we'll be able to lookup the asset.
const { id } = args;
if (!id) {
// If the ID isn't provided, we don't want to do
// anything.
return null;
}
// A mouthful for sure, but we need to use the loader
// that is available on the graph context in order to
// lookup the asset by ID.
const asset = await ctx.loaders.Assets.getByID.load(id);
if (!asset) {
// If the asset can't be found, we don't want to do
// anything.
return null;
}
// Send the asset back.
return asset;
},
},
};
```
This serves to override the default asset resolver. You can of course, override
any other field in the schema to perform whatever action your business needs
require, including adding additional resolvers! You can refer to our
[GraphQL API Docs](/talk/reference/graphql/) to see what other fields you can
override.
Without this, Talk will continue to use the "Lazy Asset Creation" to handle
resolving the `asset` edge, which is what we want to change.
_Note, you can also get to this point by running `git checkout step-2`!_
## Creating a New Asset Route
In order to create Assets now, we have to get our CMS to push those into Talk,
the easiest way to do this is by creating a custom route. We won't cover
specific CMS integrations, but will assume that there is some type of webhook
system you are able to utilize that will trigger when a new article is created.
We'll replace the contents of the `router.js` file with the following:
```js
// This file we'll create routes that will facilitate asset creation and
// updates.
const authz = require('middleware/authorization');
module.exports = router => {
// We'll respond to a POST request on the following route where the request
// must have a valid ADMIN access token.
router.post(
'/api/v1/plugin/asset-manager-example',
authz.needed('ADMIN'),
async (req, res, next) => {
// Get the graph context from the request.
const { context } = req;
// Grab from the graph context, the AssetModel that we can use to create
// the new Asset. Lots of object destructuring here, but this lets us keep
// the important business logic cleaner.
const { connectors: { models: { Assets } } } = context;
try {
// Now we can create the asset that was passed to us in the body of the
// request as JSON. Check the schema of the Asset model by looking at:
// https://github.com/coralproject/talk/blob/master/models/asset.js
await Assets.create(req.body);
// Let your webhook callback know we got it!
return res.status(204).end();
} catch (err) {
return next(err);
}
}
);
};
```
This request handler when mounted on Talk will allow your CMS to send a POST
request to `${TALK_ROOT_URL}/api/v1/plugin/asset-manager-example` with the
Asset as a JSON payload. In order to protect the endpoint from abuse, we add the
authorization middleware. This middleware essentially says, _you must be an
admin to hit this route_. We need to generate a token that can be used by your
CMS using the Talk cli tool:
```sh
# find or create an admin user that can be used as the basis for the token
./bin/cli users list
# create a token for the user with the given id
./bin/cli token create ${USER_ID} cms-token
```
You can attach the generated token to the request a few ways:
1. HTTP Header:
curl ${TALK_ROOT_URL}/api/v1/plugin/asset-manager-example \
-XPOST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
--data "${ASSET_JSON}"
2. Query Parameter:
curl ${TALK_ROOT_URL}/api/v1/plugin/asset-manager-example?access_token=${TOKEN}
-XPOST \
-H "Content-Type: application/json" \
--data "${ASSET_JSON}"
Where `${ASSET_JSON}` is the JSON for your Asset matching the
[AssetSchema](https://github.com/coralproject/talk/blob/master/models/asset.js).
_Note, you can also get to this point by running `git checkout step-3`!_
## Creating an Asset Update Route
Now imagine the situation where you decide that you want to change the url slug
of the page, or update the title, now Talk is out of sync! Let's fix that.
Update your `router.js` to the following:
```js
// This file we'll create routes that will facilitate asset creation and
// updates.
const authz = require('middleware/authorization');
module.exports = router => {
// We'll respond to a POST request on the following route where the request
// must have a valid ADMIN access token.
router.post(
'/api/v1/plugin/asset-manager-example',
authz.needed('ADMIN'),
async (req, res, next) => {
// Get the graph context from the request.
const { context } = req;
// Grab from the graph context, the AssetModel that we can use to create
// the new Asset. Lots of object destructuring here, but this lets us keep
// the important business logic cleaner.
const { connectors: { models: { Assets } } } = context;
try {
// Now we can create the asset that was passed to us in the body of the
// request as JSON. Check the schema of the Asset model by looking at:
// https://github.com/coralproject/talk/blob/master/models/asset.js
await Assets.create(req.body);
// Let your webhook callback know we got it!
return res.status(204).end();
} catch (err) {
return next(err);
}
}
);
// We'll respond to a PUT request on the following route where the request
// must also have a valid ADMIN access token.
router.put(
'/api/v1/plugin/asset-manager-example/:id',
authz.needed('ADMIN'),
async (req, res, next) => {
// Get the graph context from the request.
const { context } = req;
// Grab from the graph context, the AssetModel that we can use to update
// the Asset. Lots of object destructuring here, but this lets us keep
// the important business logic cleaner.
const { connectors: { models: { Assets } } } = context;
try {
// Now we can lookup the asset we're updating and apply out updates to
// the model atomically.
const asset = await Assets.findOneAndUpdate(
{ id: req.params.id },
req.body,
{
// We want to validate the model being updated.
runValidators: true,
}
);
if (!asset) {
// The asset indicated by the ID wasn't found, let the webhook know!
return res.status(404).end();
}
// Let your webhook callback know we got it!
return res.status(204).end();
} catch (err) {
return next(err);
}
}
);
};
```
As you can see from the previous step of [Creating a New Asset Route](#Creating-a-New-Asset-Route)
, we have added the new `PUT` route to the router. This is a simple addition
that allows your CMS to call into Talk when the asset has updated it's title,
it's url (or really anything in the [AssetSchema](https://github.com/coralproject/talk/blob/master/models/asset.js)) to keep the Talk Admin and links up to date.
Following the previous example, you can issue the request as follows:
```sh
curl ${TALK_ROOT_URL}/api/v1/plugin/asset-manager-example/${ASSET_ID} \
-XPUT \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
--data "${ASSET_JSON}"
```
The difference from the previous curl example, is that this one changes the
method from a `POST` to a `PUT`, and we add the `${ASSET_ID}` to the end of the
url.
_Note, you can also get to this point by running `git checkout step-4`!_
## Target the Asset
Now that we have a way to create and update Assets, we now need a way to
reference it. One of the most important fields in the Asset model, is the `id`.
This `id` can be one generated from your CMS, or some other system, but must
be kept consistent.
When you install Talk, and visit the admin panel, we can see under
`/admin/configure` in the tab for Tech Settings, an embed snippet:
```html
<div id="coral_talk_stream"></div>
<script src="${TALK_ROOT_URL}static/embed.js" async onload="
Coral.Talk.render(document.getElementById('coral_talk_stream'), {
talk: '${TALK_ROOT_URL}'
});
"></script>
```
We'll modify this to the following:
```html
<div id="coral_talk_stream"></div>
<script src="${TALK_ROOT_URL}static/embed.js" async onload="
Coral.Talk.render(document.getElementById('coral_talk_stream'), {
talk: '${TALK_ROOT_URL}',
asset_id: '${ASSET_ID}'
});
"></script>
```
Adding the `asset_id` parameter to the render function will accomplish a very
important task. It will provide Talk with the specific ID of the asset to
associate with the displayed page. This is important because even if you update
the URL in the future, the embed will still reference the correct Asset. The
`${ASSET_ID}` should be replaced by your CMS with the correct Asset id using
your desired scripting/templating tools.
At this point, you should have a fully built Talk plugin that can be paired with
some work on your CMS to create a fully integrated asset management pipeline!
To view the fully completed source code, visit
https://github.com/coralproject/talk-plugin-asset-manager-example.
+46
View File
@@ -1,4 +1,7 @@
const SettingsService = require('../services/settings');
const fs = require('fs');
const path = require('path');
const { merge } = require('lodash');
const {
BASE_URL,
@@ -34,6 +37,45 @@ const attachStaticLocals = locals => {
}
};
// MANIFESTS are all the manifests accessible by Talk.
const MANIFESTS = ['../dist/manifest.json', '../dist/manifest.embed.json'];
// getManifest will retrieve the manifest files and parse the JSON.
function getManifest() {
return merge(
{},
...MANIFESTS.map(f =>
fs.readFileSync(path.resolve(__dirname, f), 'utf8')
).map(JSON.parse)
);
}
/**
* resolve is a function that can be used in templates to resolve an asset from
* the manifest. In production, the manifest is cached.
*/
const resolve = (() => {
if (process.env.NODE_ENV === 'production') {
// In production, we should attempt to load the manifest early.
const manifest = getManifest();
return key => `${STATIC_URL}static/${manifest[key]}`;
}
// In dev mode, we are more forgiving and we always load the
// newest version of the manifest.
return key => {
try {
const manifest = getManifest();
return `${STATIC_URL}static/${manifest[key]}`;
} catch (err) {
console.warn(err);
return '';
}
};
})();
module.exports = async (req, res, next) => {
try {
// Attach the custom css url.
@@ -46,6 +88,10 @@ module.exports = async (req, res, next) => {
// Always attach the locals.
attachStaticLocals(res.locals);
// Resolve will help resolving paths to static files
// using the manifest.
res.locals.resolve = resolve;
// Forward the request.
next();
};
+3 -1
View File
@@ -116,7 +116,6 @@
"graphql-tag": "^1.2.3",
"graphql-tools": "^0.10.1",
"hammerjs": "^2.0.8",
"hard-source-webpack-plugin": "^0.6.0",
"helmet": "3.8.2",
"history": "^3.0.0",
"hjson": "^3.1.1",
@@ -213,6 +212,7 @@
"enzyme-adapter-react-15": "^1.0.0",
"eslint": "^4.5.0",
"eslint-plugin-mocha": "^4.11.0",
"extract-text-webpack-plugin": "^3.0.2",
"husky": "^0.14.3",
"identity-obj-proxy": "^3.0.0",
"ip": "^1.1.5",
@@ -221,11 +221,13 @@
"lint-staged": "^7.0.0",
"mocha": "^3.1.2",
"mocha-junit-reporter": "^1.12.1",
"name-all-modules-plugin": "^1.0.1",
"nightwatch": "^0.9.16",
"nodemon": "^1.11.0",
"selenium-standalone": "^6.11.0",
"sinon": "^3.2.1",
"sinon-chai": "^2.13.0",
"webpack-manifest-plugin": "^2.0.0-rc.2",
"yaml-lint": "^1.0.0"
},
"engines": {
+6 -3
View File
@@ -3,8 +3,6 @@
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Talk - Coral Admin</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.min.css">
<style media="screen">
body, #root {
width: 100%;
@@ -18,11 +16,16 @@
height: 100%;
}
</style>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="<%= resolve('coral-admin/bundle.css') %>">
<%- include partials/head %>
</head>
<body class="admin-page">
<div id="root"></div>
<script src='https://www.google.com/recaptcha/api.js?render=explicit' async defer></script>
<script src="<%= STATIC_URL %>static/coral-admin/bundle.js" charset="utf-8"></script>
<script src="<%= resolve('coral-admin/bundle.js') %>" charset="utf-8"></script>
</body>
</html>
+1 -1
View File
@@ -25,7 +25,7 @@
<p><%= body %></p>
<p><a href="<%= BASE_PATH %>admin">Admin</a> - <a href="<%= BASE_PATH %>assets">All Assets</a></p>
<div id='coralStreamEmbed'></div>
<script src="<%= STATIC_URL %>static/embed.js" async onload="
<script src="<%= resolve('embed.js') %>" async onload="
window.TalkEmbed = Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
talk: '<%= BASE_URL %>',
asset_url: '<%= asset_url ? asset_url : '' %>',
+1 -1
View File
@@ -5,6 +5,6 @@
</head>
<body>
<script type="application/json" id="auth"><%- encodeJSONForHTML(auth) %></script>
<script type="text/javascript" src="<%= STATIC_URL %>static/coral-auth-callback/bundle.js"></script>
<script type="text/javascript" src="<%= resolve('coral-auth-callback/bundle.js') %>"></script>
</body>
</html>
+5 -2
View File
@@ -2,11 +2,14 @@
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="<%= STATIC_URL %>static/embed/stream/default.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="<%= resolve('embed/stream/default.css') %>">
<link rel="stylesheet" type="text/css" href="<%= resolve('embed/stream/bundle.css') %>">
<%- include ../partials/head %>
</head>
<body class="embed-stream-page">
<div id="talk-embed-stream-container"></div>
<script src="<%= STATIC_URL %>static/embed/stream/bundle.js"></script>
<script src="<%= resolve('embed/stream/bundle.js') %>"></script>
</body>
</html>
+4 -1
View File
@@ -2,11 +2,14 @@
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="<%= resolve('coral-login/bundle.css') %>">
<%- include partials/head %>
</head>
<body>
<div id="talk-login-container"></div>
<script src='https://www.google.com/recaptcha/api.js?render=explicit' async defer></script>
<script src="<%= STATIC_URL %>static/coral-login/bundle.js"></script>
<script src="<%= resolve('coral-login/bundle.js') %>"></script>
</body>
</html>
+1 -3
View File
@@ -12,11 +12,9 @@
<link rel="icon" type="image/png" sizes="96x96" href="<%= STATIC_URL %>public/img/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="<%= STATIC_URL %>public/img/favicon-16x16.png">
<link rel="manifest" href="<%= STATIC_URL %>public/manifest.json">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<meta name="msapplication-TileColor" content="#ffffff">
<%_ if (locals.customCssUrl) { _%>
<link href="<%= customCssUrl %>" rel="stylesheet" type="text/css">
<%_ } _%>
<%- include data %>
<base href="<%= BASE_URL %>"/>
<base href="<%= BASE_URL %>"/>
+138 -76
View File
@@ -8,8 +8,13 @@ const _ = require('lodash');
const Copy = require('copy-webpack-plugin');
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const debug = require('debug')('talk:webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
// Needed to enforce stable asset hashes.
// https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31
const NameAllModulesPlugin = require('name-all-modules-plugin');
// Possibly load the config from the .env file (if there is one).
require('dotenv').config();
@@ -56,8 +61,8 @@ const config = {
output: {
path: path.join(__dirname, 'dist'),
publicPath: '',
filename: '[name].js',
chunkFilename: '[name].chunk.js',
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].chunk.js',
},
module: {
rules: [
@@ -85,11 +90,21 @@ const config = {
test: /\.yml$/,
},
{
loaders: [
'style-loader',
'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
'postcss-loader',
],
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
minimize: true,
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
'postcss-loader',
],
}),
test: /.css$/,
},
{
@@ -97,7 +112,8 @@ const config = {
test: /\.(jpg|png|gif|svg)$/,
},
{
loader: 'url-loader?limit=100000',
loader: 'url-loader',
options: { limit: 100000 },
test: /\.woff$/,
},
{
@@ -108,10 +124,15 @@ const config = {
],
},
plugins: [
new ExtractTextPlugin({
// Use contenthash instead of chunk hash see
// https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/#setting-up-hashing
filename: getPath => getPath('[name].[contenthash].css'),
}),
new Copy([
...buildEmbeds.map(embed => ({
from: path.join(__dirname, 'client', `coral-embed-${embed}`, 'style'),
to: path.join(__dirname, 'dist', 'embed', embed),
to: path.join(__dirname, 'dist', 'embed', embed, '[name].[hash].[ext]'),
})),
]),
autoprefixer,
@@ -136,7 +157,16 @@ const config = {
TALK_DEFAULT_LANG: 'en',
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new HardSourceWebpackPlugin(),
// We follow this article for stable hashes.
// https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31
//
// Chunks without names do not seem to work, so
// we have to make sure they are always named.
// https://github.com/webpack/webpack/tree/master/examples/code-splitting-specify-chunk-name
new webpack.NamedModulesPlugin(),
new webpack.NamedChunksPlugin(),
new NameAllModulesPlugin(),
],
resolveLoader: {
modules: [
@@ -249,9 +279,15 @@ if (process.env.NODE_ENV === 'production') {
// Entries
//==============================================================================
function customizeConcatArrays(objValue, srcValue) {
if (_.isArray(objValue)) {
return objValue.concat(srcValue);
}
}
// Applies the base configuration to the following entries.
const applyConfig = (entries, root = {}) =>
_.merge(
_.mergeWith(
{},
config,
{
@@ -274,9 +310,17 @@ const applyConfig = (entries, root = {}) =>
{}
),
},
root
root,
customizeConcatArrays
);
// Hack until this issue is resolved https://github.com/webpack-contrib/copy-webpack-plugin/issues/104
const copyWebpackPluginManifestHack = file => {
// Remove hash in manifest key
file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
return file;
};
module.exports = [
// Coral Embed
applyConfig(
@@ -291,82 +335,100 @@ module.exports = [
{
output: {
library: 'Coral',
// don't hash the embed.
filename: '[name].js',
},
plugins: [
new ManifestPlugin({
fileName: 'manifest.embed.json',
map: copyWebpackPluginManifestHack,
}),
],
}
),
// All framework targets/embeds/plugins.
applyConfig([
// Load in all the targets.
...buildTargets.map(target => {
let disablePolyfill = false;
if (typeof target !== 'string') {
disablePolyfill = target.disablePolyfill;
target = target.name;
}
applyConfig(
[
// Load in all the targets.
...buildTargets.map(target => {
let disablePolyfill = false;
if (typeof target !== 'string') {
disablePolyfill = target.disablePolyfill;
target = target.name;
}
return {
name: `${target}/bundle`,
path: path.join(__dirname, 'client/', target, '/src/index'),
disablePolyfill,
};
}),
return {
name: `${target}/bundle`,
path: path.join(__dirname, 'client/', target, '/src/index'),
disablePolyfill,
};
}),
// Load in all the embeds.
...buildEmbeds.map(embed => ({
name: `embed/${embed}/bundle`,
path: path.join(
__dirname,
'client/',
`coral-embed-${embed}`,
'/src/index'
),
})),
// Load in all the embeds.
...buildEmbeds.map(embed => ({
name: `embed/${embed}/bundle`,
path: path.join(
__dirname,
'client/',
`coral-embed-${embed}`,
'/src/index'
),
})),
// Load in all the plugin entries.
...targetPlugins.reduce((entries, plugin) => {
// Introspect the path to find a targets folder.
let folder = path.dirname(plugin.path);
let files = fs.readdirSync(folder);
// Load in all the plugin entries.
...targetPlugins.reduce((entries, plugin) => {
// Introspect the path to find a targets folder.
let folder = path.dirname(plugin.path);
let files = fs.readdirSync(folder);
// While the folder does not contain the targets folder...
while (!files.includes('targets')) {
// Try to go up a folder.
folder = path.normalize(path.join(folder, '..'));
// While the folder does not contain the targets folder...
while (!files.includes('targets')) {
// Try to go up a folder.
folder = path.normalize(path.join(folder, '..'));
// And as long as we haven't gone too high
if (
!(
folder.includes(path.join(__dirname, 'node_modules')) ||
!folder.includes(path.join(__dirname, 'plugins'))
)
) {
// And as long as we haven't gone too high
if (
!(
folder.includes(path.join(__dirname, 'node_modules')) ||
!folder.includes(path.join(__dirname, 'plugins'))
)
) {
throw new Error(
`target plugin ${plugin.name} does not have a 'targets' folder`
);
}
files = fs.readdirSync(folder);
}
// List all targets available in that folder.
folder = path.join(folder, 'targets');
let targets = fs.readdirSync(folder);
if (targets.length === 0) {
throw new Error(
`target plugin ${plugin.name} does not have a 'targets' folder`
`target plugin ${
plugin.name
} has no targets in it's target folder ${folder}`
);
}
files = fs.readdirSync(folder);
}
// List all targets available in that folder.
folder = path.join(folder, 'targets');
let targets = fs.readdirSync(folder);
if (targets.length === 0) {
throw new Error(
`target plugin ${
plugin.name
} has no targets in it's target folder ${folder}`
return entries.concat(
targets.map(target => ({
name: `plugin/${plugin.name}/${target}/bundle`,
path: path.join(folder, target, 'index'),
}))
);
}
return entries.concat(
targets.map(target => ({
name: `plugin/${plugin.name}/${target}/bundle`,
path: path.join(folder, target, 'index'),
}))
);
}, []),
]),
}, []),
],
{
plugins: [
new ManifestPlugin({
fileName: 'manifest.json',
map: copyWebpackPluginManifestHack,
}),
],
}
),
];
+141 -105
View File
@@ -598,7 +598,7 @@ async@^1.4.0, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.1.2, async@^2.1.4, async@~2.6.0:
async@^2.1.2, async@^2.1.4, async@^2.4.1, async@~2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
dependencies:
@@ -1354,7 +1354,7 @@ bluebird@3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
bluebird@^3.0.6, bluebird@^3.1.1, bluebird@^3.2.2, bluebird@^3.3.4, bluebird@^3.4.0, bluebird@^3.4.6, bluebird@^3.5.0:
bluebird@^3.0.6, bluebird@^3.1.1, bluebird@^3.2.2, bluebird@^3.3.4, bluebird@^3.4.0, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@@ -1415,13 +1415,20 @@ boxen@^1.2.1:
term-size "^1.2.0"
widest-line "^2.0.0"
brace-expansion@^1.0.0, brace-expansion@^1.1.7:
brace-expansion@^1.0.0:
version "1.1.8"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
braces@^1.8.2:
version "1.8.5"
resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
@@ -1635,23 +1642,23 @@ bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
cacache@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.1.tgz#3e05f6e616117d9b54665b1b20c8aeb93ea5d36f"
cacache@^10.0.1, cacache@^10.0.4:
version "10.0.4"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
dependencies:
bluebird "^3.5.0"
bluebird "^3.5.1"
chownr "^1.0.1"
glob "^7.1.2"
graceful-fs "^4.1.11"
lru-cache "^4.1.1"
mississippi "^1.3.0"
mississippi "^2.0.0"
mkdirp "^0.5.1"
move-concurrently "^1.0.1"
promise-inflight "^1.0.1"
rimraf "^2.6.1"
ssri "^5.0.0"
rimraf "^2.6.2"
ssri "^5.2.4"
unique-filename "^1.1.0"
y18n "^3.2.1"
y18n "^4.0.0"
cache-base@^1.0.1:
version "1.0.1"
@@ -2211,7 +2218,7 @@ concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0:
concat-stream@^1.4.7, concat-stream@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
dependencies:
@@ -2219,6 +2226,14 @@ concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
concat-stream@^1.5.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26"
dependencies:
inherits "^2.0.3"
readable-stream "^2.2.2"
typedarray "^0.0.6"
configstore@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90"
@@ -2334,18 +2349,16 @@ copy-descriptor@^0.1.0:
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
copy-webpack-plugin@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.3.0.tgz#cfdf4d131c78d66917a1bb863f86630497aacf42"
version "4.5.1"
resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.5.1.tgz#fc4f68f4add837cc5e13d111b20715793225d29c"
dependencies:
cacache "^10.0.1"
cacache "^10.0.4"
find-cache-dir "^1.0.0"
globby "^7.1.1"
is-glob "^4.0.0"
loader-utils "^0.2.15"
lodash "^4.3.0"
loader-utils "^1.1.0"
minimatch "^3.0.4"
p-limit "^1.0.0"
pify "^3.0.0"
serialize-javascript "^1.4.0"
core-js@^1.0.0, core-js@^1.1.1:
@@ -2828,10 +2841,6 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
detect-indent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
detect-libc@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-0.2.0.tgz#47fdf567348a17ec25fcbf0b9e446348a76f9fb5"
@@ -2989,9 +2998,9 @@ duplexer@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.1.2, duplexify@^3.4.2:
version "3.5.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
duplexify@^3.4.2, duplexify@^3.5.3:
version "3.5.4"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4"
dependencies:
end-of-stream "^1.0.0"
inherits "^2.0.1"
@@ -3062,8 +3071,8 @@ encoding@^0.1.11:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
dependencies:
once "^1.4.0"
@@ -3630,6 +3639,15 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
extract-text-webpack-plugin@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7"
dependencies:
async "^2.4.1"
loader-utils "^1.1.0"
schema-utils "^0.3.0"
webpack-sources "^1.0.1"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@@ -3923,6 +3941,16 @@ fs-extra@^0.24.0:
path-is-absolute "^1.0.0"
rimraf "^2.2.8"
fs-extra@^0.30.0:
version "0.30.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^2.1.0"
klaw "^1.0.0"
path-is-absolute "^1.0.0"
rimraf "^2.2.8"
fs-extra@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
@@ -4279,7 +4307,7 @@ gql-utils@^0.0.2:
bluebird "^3.4.6"
glob "^7.1.1"
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
@@ -4419,19 +4447,6 @@ har-validator@~5.0.3:
ajv "^5.1.0"
har-schema "^2.0.0"
hard-source-webpack-plugin@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.6.0.tgz#ec2f60068a8d1f358439b7b1587f1c64fe642eda"
dependencies:
lodash "^4.15.0"
mkdirp "^0.5.1"
node-object-hash "^1.2.0"
rimraf "^2.6.2"
tapable "^1.0.0-beta.5"
webpack-core "~0.6.0"
webpack-sources "^1.0.1"
write-json-file "^2.3.0"
harmony-reflect@^1.4.6:
version "1.5.1"
resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.5.1.tgz#b54ca617b00cc8aef559bbb17b3d85431dc7e329"
@@ -6246,6 +6261,12 @@ kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
klaw@^1.0.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
optionalDependencies:
graceful-fs "^4.1.9"
kue@0.11.6:
version "0.11.6"
resolved "https://registry.yarnpkg.com/kue/-/kue-0.11.6.tgz#5b76916bcedd56636a107861471c63c94611860a"
@@ -6445,7 +6466,7 @@ loader-runner@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
loader-utils@^0.2.12, loader-utils@^0.2.15:
loader-utils@^0.2.12:
version "0.2.17"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
dependencies:
@@ -6742,14 +6763,14 @@ lodash.values@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
lodash@^4.13.1, lodash@^4.17.5, lodash@~4.17.4:
"lodash@>=3.5 <5", lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.4:
version "4.17.5"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
@@ -6810,13 +6831,20 @@ lru-cache@^2.5.0, lru-cache@~2.6.5:
version "2.6.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5"
lru-cache@^4.0.1, lru-cache@^4.1.1:
lru-cache@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
lru-cache@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f"
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
lunr@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.1.6.tgz#671d2321c4c5bc4c522914953d1c54d612f60aa7"
@@ -6833,8 +6861,8 @@ mailcomposer@4.0.1:
libmime "3.0.0"
make-dir@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51"
version "1.2.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b"
dependencies:
pify "^3.0.0"
@@ -7079,9 +7107,9 @@ minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
mississippi@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5"
mississippi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
dependencies:
concat-stream "^1.5.0"
duplexify "^3.4.2"
@@ -7089,7 +7117,7 @@ mississippi@^1.3.0:
flush-write-stream "^1.0.0"
from2 "^2.1.0"
parallel-transform "^1.1.0"
pump "^1.0.0"
pump "^2.0.1"
pumpify "^1.3.3"
stream-each "^1.1.0"
through2 "^2.0.0"
@@ -7278,6 +7306,10 @@ mv@~2:
ncp "~2.0.0"
rimraf "~2.4.0"
name-all-modules-plugin@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/name-all-modules-plugin/-/name-all-modules-plugin-1.0.1.tgz#0abfb6ad835718b9fb4def0674e06657a954375c"
nan@^2.3.0, nan@^2.3.3, nan@^2.6.2:
version "2.8.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a"
@@ -7479,10 +7511,6 @@ node-notifier@^5.0.2:
shellwords "^0.1.0"
which "^1.2.12"
node-object-hash@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.3.0.tgz#7f294f5afec6b08d713e40d40a95ec793e05baf3"
node-pre-gyp@^0.6.36, node-pre-gyp@^0.6.39:
version "0.6.39"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649"
@@ -7936,8 +7964,10 @@ p-finally@^1.0.0:
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
p-limit@^1.0.0, p-limit@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
dependencies:
p-try "^1.0.0"
p-locate@^2.0.0:
version "2.0.0"
@@ -7949,6 +7979,10 @@ p-map@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
p-try@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
pac-proxy-agent@1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz#34a385dfdf61d2f0ecace08858c745d3e791fd4d"
@@ -8788,6 +8822,10 @@ process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
process-nextick-args@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
@@ -8982,13 +9020,20 @@ pump@^1.0.0, pump@^1.0.1:
end-of-stream "^1.1.0"
once "^1.3.1"
pumpify@^1.3.3:
version "1.3.5"
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b"
pump@^2.0.0, pump@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
dependencies:
duplexify "^3.1.2"
inherits "^2.0.1"
pump "^1.0.0"
end-of-stream "^1.1.0"
once "^1.3.1"
pumpify@^1.3.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.4.0.tgz#80b7c5df7e24153d03f0e7ac8a05a5d068bd07fb"
dependencies:
duplexify "^3.5.3"
inherits "^2.0.3"
pump "^2.0.0"
punycode@1.3.2:
version "1.3.2"
@@ -9343,14 +9388,14 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.4, readable-stream@^2.1.5, readable-stream@^2.2.2:
version "2.3.5"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
@@ -9373,6 +9418,18 @@ readable-stream@1.1.x:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@2, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
safe-buffer "~5.1.1"
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
readable-stream@2.2.7:
version "2.2.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1"
@@ -10254,20 +10311,10 @@ sort-keys@^1.0.0:
dependencies:
is-plain-obj "^1.0.0"
sort-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
dependencies:
is-plain-obj "^1.0.0"
source-list-map@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
source-list-map@~0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
source-map-resolve@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a"
@@ -10300,7 +10347,7 @@ source-map@0.1.x:
dependencies:
amdefine ">=0.0.4"
source-map@0.4.x, source-map@^0.4.2, source-map@^0.4.4, source-map@~0.4.1:
source-map@0.4.x, source-map@^0.4.2, source-map@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
dependencies:
@@ -10362,11 +10409,11 @@ sshpk@^1.7.0:
jsbn "~0.1.0"
tweetnacl "~0.14.0"
ssri@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.0.0.tgz#13c19390b606c821f2a10d02b351c1729b94d8cf"
ssri@^5.2.4:
version "5.3.0"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06"
dependencies:
safe-buffer "^5.1.0"
safe-buffer "^5.1.1"
stack-trace@0.0.x:
version "0.0.10"
@@ -10711,10 +10758,6 @@ tapable@^0.2.7:
version "0.2.8"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
tapable@^1.0.0-beta.5:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2"
tar-fs@^1.13.0:
version "1.16.0"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.0.tgz#e877a25acbcc51d8c790da1c57c9cf439817b896"
@@ -11391,12 +11434,12 @@ webidl-conversions@^4.0.0, webidl-conversions@^4.0.1, webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
webpack-core@~0.6.0:
version "0.6.9"
resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2"
webpack-manifest-plugin@^2.0.0-rc.2:
version "2.0.0-rc.2"
resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.0.0-rc.2.tgz#7e12abb805795fe256b085a214a15d9568f0e692"
dependencies:
source-list-map "~0.1.7"
source-map "~0.4.1"
fs-extra "^0.30.0"
lodash ">=3.5 <5"
webpack-sources@^1.0.1, webpack-sources@^1.0.2, webpack-sources@^1.1.0:
version "1.1.0"
@@ -11578,17 +11621,6 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.1.0:
imurmurhash "^0.1.4"
signal-exit "^3.0.2"
write-json-file@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f"
dependencies:
detect-indent "^5.0.0"
graceful-fs "^4.1.2"
make-dir "^1.0.0"
pify "^3.0.0"
sort-keys "^2.0.0"
write-file-atomic "^2.0.0"
write@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
@@ -11642,6 +11674,10 @@ y18n@^3.2.0, y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"