+
-
+
{this.props.showFeaturedLabel && this.renderFeaturedProductLabel()}
{this.renderMedia()}
- {this.renderOverlay()}
-
{this.renderAdditionalMedia()}
- {!this.props.isSearch && this.renderNotices()}
+ {!isSearch && this.renderNotices()}
{this.renderGridContent()}
);
-
- if (this.props.canEdit) {
- return (
- this.props.connectDropTarget(
- this.props.connectDragSource(productItem)
- )
- );
- }
-
- return productItem;
}
}
-export default ProductGridItems;
-
+replaceComponent("ProductGridItemCustomer", ProductGridItem);
-replaceComponent("ProductGridItems", ProductGridItems);
+export default ProductGridItem;
diff --git a/client/components/product-variant/index.js b/client/components/product-variant/index.js
index 1f2a9bf..c3f646f 100644
--- a/client/components/product-variant/index.js
+++ b/client/components/product-variant/index.js
@@ -1,6 +1,2 @@
-import "./templates/categoryGrid.html";
-import "./templates/categoryGrid.js";
-import "./categories";
-import "./products";
-import "./productGrid";
-import "./productGridItems";
+import "./customer/productGrid";
+import "./customer/productGridItem";
diff --git a/client/components/product-variant/productGrid.js b/client/components/product-variant/productGrid.js
deleted file mode 100644
index e51c765..0000000
--- a/client/components/product-variant/productGrid.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import React from "react";
-import PropTypes from "prop-types";
-import { Components, replaceComponent } from "@reactioncommerce/reaction-components";
-
-import { default as ProductGridCore } from "/imports/plugins/included/product-variant/components/productGrid";
-import { Reaction } from "/client/api";
-
-
-class ProductGrid extends ProductGridCore {
- static propTypes = {
- products: PropTypes.array,
- shouldRenderSectionHeader: PropTypes.bool
- }
-
- static defaultProps = {
- shouldRenderSectionHeader: true
- }
-
- renderProductGridItems = (products) => {
- if (Array.isArray(products)) {
- const slug = Reaction.Router.getParam("slug");
- if (slug) {
- const insertAt = products.length && Math.ceil(products.length / 2) || 0;
- products.splice(insertAt, 0, { src: "/plugins/reaction-swag-shop/mountain-road.jpg" });
- }
- return products.map((product, index) => {
- if (product.src) {
- return (
-
-
-
- );
- }
-
- return (
-
- );
- });
- }
- return (
-
- );
- }
-
- render() {
- return (
-
- {this.props.shouldRenderSectionHeader &&
-
}
-
-
-
- {this.renderProductGridItems(this.props.products)}
-
-
-
-
- );
- }
-}
-
-replaceComponent("ProductGrid", ProductGrid);
-
-export default ProductGrid;
diff --git a/client/components/product-variant/templates/categoryGrid.html b/client/components/product-variant/templates/categoryGrid.html
deleted file mode 100644
index 18c01fb..0000000
--- a/client/components/product-variant/templates/categoryGrid.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- {{>React component=component}}
-
-
diff --git a/client/components/product-variant/templates/categoryGrid.js b/client/components/product-variant/templates/categoryGrid.js
deleted file mode 100644
index c8450c0..0000000
--- a/client/components/product-variant/templates/categoryGrid.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Components } from "@reactioncommerce/reaction-components";
-import { Template } from "meteor/templating";
-
-Template.categoryGrid.helpers({
- component() {
- return Components.Categories;
- }
-});
diff --git a/client/components/similar-products.js b/client/components/similar-products.js
index 79caf5d..a4bd25f 100644
--- a/client/components/similar-products.js
+++ b/client/components/similar-products.js
@@ -2,14 +2,13 @@ import React, { Component } from "react";
import PropTypes from "prop-types";
import { Components } from "@reactioncommerce/reaction-components";
import { Reaction } from "/client/api/index";
-import { Media } from "/lib/collections/index";
import { ReactionProduct } from "/lib/api";
class SimilarProducts extends Component {
static propTypes = {
- products: PropTypes.arrayOf(PropTypes.object),
- productMedia: PropTypes.func
+ productMedia: PropTypes.func,
+ products: PropTypes.arrayOf(PropTypes.object)
}
handleClick = (event, handle) => {
@@ -23,19 +22,7 @@ class SimilarProducts extends Component {
render() {
const { products } = this.props;
if (products && products.length > 0) {
- const mediaMap = {};
- products.map((product) => {
- const media = Media.find({
- "metadata.productId": product._id
- }, {
- sort: {
- "metadata.priority": 1
- }
- }, { limit: 1 }).fetch();
- if (media && media[0]) {
- mediaMap[product._id] = media[0];
- }
- });
+ const currentTag = ReactionProduct.getTag();
return (
@@ -44,18 +31,15 @@ class SimilarProducts extends Component {
- {products.map((product, index) =>
-
+ this.props.productMedia(index)}
- onClick={(event) => this.handleClick(event, product.handle)}
- />
- )}
+ />)}
-
- );
+ );
}
return null;
}
diff --git a/client/containers/product-variant/index.js b/client/containers/product-variant/index.js
index 1e02130..34b15ef 100644
--- a/client/containers/product-variant/index.js
+++ b/client/containers/product-variant/index.js
@@ -1 +1 @@
-import "./productsContainer";
+import "./productsContainerCustomer";
diff --git a/client/containers/product-variant/productsContainer.js b/client/containers/product-variant/productsContainer.js
deleted file mode 100644
index 04fbbfa..0000000
--- a/client/containers/product-variant/productsContainer.js
+++ /dev/null
@@ -1,234 +0,0 @@
-import _ from "lodash";
-import React, { Component } from "react";
-import { PropTypes } from "prop-types";
-import { Meteor } from "meteor/meteor";
-import { Session } from "meteor/session";
-import { Reaction } from "/client/api";
-import { ReactionProduct } from "/lib/api";
-import { applyProductRevision } from "/lib/api/products";
-import { Products, Tags, Shops } from "/lib/collections";
-import { replaceComponent, getHOCs, composeWithTracker } from "@reactioncommerce/reaction-components";
-import ProductsComponent from "../../components/product-variant/products";
-import { ITEMS_INCREMENT } from "/client/config/defaults";
-
-/*
- * Customized version of imports/plugins/included/product-variant/containers/productsContainer.js
- * It subscribes to featured products only for landing page section "Products we love"
- */
-
-// The following two functions are copied almost verbatim and should not be necessary, if wrapComponent would
-// allow to pass general properties
-function loadMoreProducts() {
- let threshold;
- const target = document.querySelectorAll("#productScrollLimitLoader");
- let scrollContainer = document.querySelectorAll("#container-main");
- if (scrollContainer.length === 0) {
- scrollContainer = window;
- }
-
- if (target.length) {
- threshold = scrollContainer[0].scrollHeight - scrollContainer[0].scrollTop === scrollContainer[0].clientHeight;
-
- if (threshold) {
- if (!target[0].getAttribute("visible")) {
- target[0].setAttribute("productScrollLimit", true);
- Session.set("productScrollLimit", Session.get("productScrollLimit") + ITEMS_INCREMENT || 24);
- }
- } else {
- if (target[0].getAttribute("visible")) {
- target[0].setAttribute("visible", false);
- }
- }
- }
-}
-
-const wrapComponent = (Comp) => (
- class ProductsContainer extends Component {
- static propTypes = {
- canLoadMoreProducts: PropTypes.bool,
- products: PropTypes.array,
- productsSubscription: PropTypes.object,
- showNotFound: PropTypes.bool,
- tags: PropTypes.object
- };
-
- constructor(props) {
- super(props);
- this.state = {
- initialLoad: true
- };
-
- this.ready = this.ready.bind(this);
- this.loadMoreProducts = this.loadMoreProducts.bind(this);
- }
-
- ready = () => {
- if (this.props.showNotFound === true) {
- return false;
- }
-
- const isInitialLoad = this.state.initialLoad === true;
- const isReady = this.props.productsSubscription.ready();
-
- if (isInitialLoad === false) {
- return true;
- }
-
- if (isReady) {
- return true;
- }
-
- return false;
- }
-
- loadMoreProducts = () => {
- return this.props.canLoadMoreProducts === true;
- }
-
- loadProducts = (event) => {
- event.preventDefault();
- this.setState({
- initialLoad: false
- });
- loadMoreProducts();
- }
-
- render() {
- return (
-
- );
- }
- }
-);
-
-function composer(props, onData) {
- window.prerenderReady = false;
-
- let canLoadMoreProducts = false;
-
- const slug = Reaction.Router.getParam("slug");
- const shopIdOrSlug = Reaction.Router.getParam("shopSlug");
-
- const tag = Tags.findOne({ slug }) || Tags.findOne(slug);
- // BOF: swag shop featuredProduct filter
- // const scrollLimit = Session.get("productScrollLimit");
- // EOF: swag shop featuredProduct filter
- let tags = {}; // this could be shop default implementation needed
- let shopIds = {};
-
- if (tag) {
- tags = { tags: [tag._id] };
- }
-
- if (shopIdOrSlug) {
- shopIds = { shops: [shopIdOrSlug] };
- }
-
- // if we get an invalid slug, don't return all products
- if (!tag && slug) {
- onData(null, {
- showNotFound: true
- });
-
- return;
- }
-
- const currentTag = ReactionProduct.getTag();
-
- const sort = {
- [`positions.${currentTag}.position`]: 1,
- [`positions.${currentTag}.createdAt`]: 1,
- createdAt: 1
- };
-
- // Get the current user and their preferences
- const user = Meteor.user();
- const prefs = user && user.profile && user.profile.preferences;
-
- // Edit mode is true by default
- let editMode = true;
-
- // if we have a "viewAs" preference and the preference is not set to "administrator", then edit mode is false
- if (prefs && prefs["reaction-dashboard"] && prefs["reaction-dashboard"].viewAs) {
- if (prefs["reaction-dashboard"].viewAs !== "administrator") {
- editMode = false;
- }
- }
-
- const queryParams = Object.assign({}, tags, Reaction.Router.current().queryParams, shopIds);
-
- // BOF: swag shop featuredProduct filter
- let swagShopScrollLimit;
- if (slug) {
- // e.g. route /tag/:slug?
- swagShopScrollLimit = Session.get("productScrollLimit");
- } else {
- // e.g. index route /
- // Only interested in first 3 products for "Products we love" section
- swagShopScrollLimit = 3;
- queryParams.featuredProductLabel = ""; // subscribe to all featured products, regardless of label
- }
-
- const productsSubscription = Meteor.subscribe("Products", swagShopScrollLimit, queryParams, sort, editMode);
- // EOF: swag shop featuredProduct filter
-
- if (productsSubscription.ready()) {
- window.prerenderReady = true;
- }
-
- const activeShopsIds = Shops.find({
- $or: [
- { "workflow.status": "active" },
- { _id: Reaction.getPrimaryShopId() }
- ]
- }).fetch().map(activeShop => activeShop._id);
-
- const productCursor = Products.find({
- ancestors: [],
- type: { $in: ["simple"] },
- shopId: { $in: activeShopsIds }
- });
-
- const products = productCursor.map((product) => {
- return applyProductRevision(product);
- });
-
- const sortedProducts = ReactionProduct.sortProducts(products, currentTag);
-
- canLoadMoreProducts = productCursor.count() >= Session.get("productScrollLimit");
- const stateProducts = sortedProducts;
-
- Session.set("productGrid/products", sortedProducts);
-
- const isActionViewOpen = Reaction.isActionViewOpen();
- if (isActionViewOpen === false) {
- Session.set("productGrid/selectedProducts", []);
- }
-
- // BOF: swag shop tags for category tiles
- tags = Tags.find({ isTopLevel: true }, { sort: { position: 1 } }).fetch();
- tags = _.sortBy(tags, "position"); // puts tags without position at end of array
-
- // EOF: swag shop tags for category tiles
-
- onData(null, {
- productsSubscription,
- products: stateProducts,
- canLoadMoreProducts,
- tags
- });
-}
-
-const higherOrderFuncs = getHOCs("Products");
-// We are interested in replacing the composer HOC only.
-higherOrderFuncs[0] = composeWithTracker(composer);
-higherOrderFuncs[1] = wrapComponent;
-replaceComponent("Products", ProductsComponent);
diff --git a/client/containers/product-variant/productsContainerCustomer.js b/client/containers/product-variant/productsContainerCustomer.js
new file mode 100644
index 0000000..47fe1c7
--- /dev/null
+++ b/client/containers/product-variant/productsContainerCustomer.js
@@ -0,0 +1,119 @@
+import _ from "lodash";
+import { composeWithTracker, getHOCs, replaceComponent } from "@reactioncommerce/reaction-components";
+// import { ReactiveVar } from "meteor/reactive-var";
+import { Meteor } from "meteor/meteor";
+import { Session } from "meteor/session";
+import { Reaction } from "/client/api";
+import { ReactionProduct } from "/lib/api";
+import { Catalog, Tags, Shops } from "/lib/collections";
+import ProductGrid from "../../components/product-variant/customer/productGrid";
+
+// const reactiveProductIds = new ReactiveVar([], (oldVal, newVal) => JSON.stringify(oldVal.sort()) === JSON.stringify(newVal.sort()));
+
+/*
+ * Customized version of imports/plugins/included/product-variant/containers/productsContainerCustomer.js
+ * It subscribes to featured products only for landing page section "Products we love"
+ */
+function composer(props, onData) {
+ window.prerenderReady = false;
+
+ let canLoadMoreProducts = false;
+
+ const slug = Reaction.Router.getParam("slug");
+ const shopIdOrSlug = Reaction.Router.getParam("shopSlug");
+
+ const tag = Tags.findOne({ slug }) || Tags.findOne(slug);
+ // BOF: swag shop featuredProduct filter
+ // const scrollLimit = Session.get("productScrollLimit");
+ // EOF: swag shop featuredProduct filter
+
+ let tags = {}; // this could be shop default implementation needed
+ let shopIds = {};
+
+ if (tag) {
+ tags = { tags: [tag._id] };
+ }
+
+ if (shopIdOrSlug) {
+ shopIds = { shops: [shopIdOrSlug] };
+ }
+
+ // if we get an invalid slug, don't return all products
+ if (!tag && slug) {
+ onData(null, {
+ showNotFound: true
+ });
+
+ return;
+ }
+
+ const currentTag = ReactionProduct.getTag();
+
+ const sort = {
+ [`positions.${currentTag}.position`]: 1,
+ [`positions.${currentTag}.createdAt`]: 1,
+ createdAt: 1
+ };
+
+ const queryParams = Object.assign({}, tags, Reaction.Router.current().query, shopIds);
+ // BOF: swag shop featuredProduct filter
+ let swagShopScrollLimit;
+ if (slug) {
+ // e.g. route /tag/:slug?
+ swagShopScrollLimit = Session.get("productScrollLimit");
+ } else {
+ // e.g. index route /
+ // Only interested in first 3 products for "Products we love" section
+ swagShopScrollLimit = 3;
+ queryParams.featuredProductLabel = ""; // subscribe to all featured products, regardless of label
+ }
+
+ const productsSubscription = Meteor.subscribe("Products/grid", swagShopScrollLimit, queryParams, sort);
+ // EOF: swag shop featuredProduct filter
+
+ if (productsSubscription.ready()) {
+ window.prerenderReady = true;
+ }
+
+ const activeShopsIds = Shops.find({
+ $or: [
+ { "workflow.status": "active" },
+ { _id: Reaction.getPrimaryShopId() }
+ ]
+ }).map((activeShop) => activeShop._id);
+
+ const productCursor = Catalog.find({
+ ancestors: [],
+ type: { $in: ["product-simple"] },
+ shopId: { $in: activeShopsIds }
+ }, {
+ $sort: sort
+ });
+
+ canLoadMoreProducts = productCursor.count() >= Session.get("productScrollLimit");
+
+ // BOF: swag shop tags for category tiles
+ tags = Tags.find({ isTopLevel: true }, { sort: { position: 1 } }).fetch();
+ tags = _.sortBy(tags, "position"); // puts tags without position at end of array
+ // EOF: swag shop tags for category tiles
+
+ const products = productCursor.fetch();
+ const productIds = products.map((p) => p._id);
+
+ const mediaSub = Meteor.subscribe("ProductGridMedia", productIds);
+ // reactiveProductIds.set(productIds);
+
+ if (mediaSub.ready()) {
+ onData(null, {
+ canLoadMoreProducts,
+ products,
+ productsSubscription,
+ tags
+ });
+ }
+}
+
+const higherOrderFuncs = getHOCs("ProductsCustomer");
+higherOrderFuncs[0] = composeWithTracker(composer);
+
+replaceComponent("ProductsCustomer", ProductGrid);
diff --git a/client/containers/similar-products.js b/client/containers/similar-products.js
index a9920e8..0615942 100644
--- a/client/containers/similar-products.js
+++ b/client/containers/similar-products.js
@@ -1,39 +1,30 @@
import { Meteor } from "meteor/meteor";
+// import { ReactiveVar } from "meteor/reactive-var";
import { registerComponent } from "@reactioncommerce/reaction-components";
import { composeWithTracker } from "/imports/plugins/core/components/lib";
-import { Tags, Products } from "/lib/collections";
+import { Catalog } from "/lib/collections";
import SimilarProducts from "../components/similar-products";
-import { Media } from "../../../../../../lib/collections";
+// const reactiveProductIds = new ReactiveVar([], (oldVal, newVal) => JSON.stringify(oldVal.sort()) === JSON.stringify(newVal.sort()));
+
function composer(props, onData) {
const { product } = props;
- const ProductsSub = Meteor.subscribe("Products", 100);
- if (ProductsSub.ready()) {
- const tag = Tags.findOne({ name: product.relatedTag }, { _id: 1 });
- let similarProducts = [];
- if (tag) {
- similarProducts = Products.find({
- hashtags: tag._id,
- ancestors: { $size: 0 }
- }).fetch();
- }
-
- const productMedia = (index) => {
- const media = Media.findOne({
- "metadata.productId": similarProducts[index]._id,
- "metadata.toGrid": 1
- }, {
- sort: { "metadata.priority": 1, "uploadedAt": 1 }
+ const queryParams = {
+ relatedTag: product.relatedTag ? product.relatedTag : ""
+ };
+ const productsSub = Meteor.subscribe("Products/grid", 5, queryParams);
+ if (productsSub.ready()) {
+ const products = Catalog.find();
+ const productIds = products.map((p) => p._id);
+ // reactiveProductIds.set(productIds);
+ const mediaSub = Meteor.subscribe("ProductGridMedia", productIds);
+ if (mediaSub.ready()) {
+ onData(null, {
+ ...props,
+ products: products.fetch()
});
- return media instanceof FS.File ? media : false;
- };
-
- onData(null, {
- ...props,
- productMedia: productMedia,
- products: similarProducts
- });
+ }
}
}
diff --git a/client/styles/classes/footer.less b/client/styles/classes/footer.less
index 7ee0466..3c77289 100644
--- a/client/styles/classes/footer.less
+++ b/client/styles/classes/footer.less
@@ -63,9 +63,9 @@
}
}
}
-
.rui.tagnav {
background-color: inherit;
+ height: auto;
.navbar-items {
padding: 0;
}
diff --git a/client/styles/classes/header.less b/client/styles/classes/header.less
index 3f0a543..228b118 100644
--- a/client/styles/classes/header.less
+++ b/client/styles/classes/header.less
@@ -277,5 +277,4 @@ html .rui.navbar {
height: 16px;
padding-top: 9px;
text-align: center;
- width: 286px;
}
diff --git a/lib/collections/schemas/swagProduct.js b/lib/collections/schemas/swagProduct.js
index 58fd05a..900025f 100644
--- a/lib/collections/schemas/swagProduct.js
+++ b/lib/collections/schemas/swagProduct.js
@@ -1,45 +1,28 @@
import { Meteor } from "meteor/meteor";
-import { SimpleSchema } from "meteor/aldeed:simple-schema";
import { Product } from "/lib/collections/schemas/index";
import { Products } from "/lib/collections/index";
-import { getSlug } from "/lib/api/index";
-import { getSchemas, registerSchema } from "@reactioncommerce/reaction-collections";
+import { registerSchema } from "@reactioncommerce/reaction-collections";
-const ExtendedSchema = new SimpleSchema([
- Product,
- {
- featuredProductLabel: {
- optional: true,
- type: String
- },
- relatedTag: {
- optional: true,
- type: String,
- autoValue: function () {
- const isSimpleProduct = this.siblingField("type").value === "simple";
- if (isSimpleProduct && this.operator === "$set") {
- const productHandle = this.siblingField("handle").value;
- const slug = getSlug(`${productHandle} related`);
- Meteor.call("createTag", slug);
- return slug;
- }
+
+const ExtendedSchema = Product.clone().extend({
+ featuredProductLabel: {
+ optional: true,
+ type: String
+ },
+ relatedTag: {
+ optional: true,
+ type: String,
+ autoValue() {
+ const isSimpleProduct = this.siblingField("type").value === "simple";
+ if (isSimpleProduct && this.operator === "$set") {
+ const productHandle = this.siblingField("handle").value;
+ const slug = `${productHandle}-related`;
+ Meteor.call("createTag", slug);
+ return slug;
}
}
}
-]);
+});
+
Products.attachSchema(ExtendedSchema, { replace: true, selector: { type: "simple" } });
registerSchema("Product", ExtendedSchema);
-
-const Schemas = getSchemas();
-
-const ExtendedFilters = new SimpleSchema([
- Schemas.filters,
- {
- featuredProductLabel: {
- type: String,
- optional: true
- }
- }
-]);
-
-registerSchema("filters", ExtendedFilters);
diff --git a/lib/collections/schemas/tags.js b/lib/collections/schemas/tags.js
index be5f9b6..131e92d 100644
--- a/lib/collections/schemas/tags.js
+++ b/lib/collections/schemas/tags.js
@@ -1,33 +1,29 @@
-import { SimpleSchema } from "meteor/aldeed:simple-schema";
import { Tag } from "/lib/collections/schemas";
import { Tags } from "/lib/collections";
import { registerSchema } from "@reactioncommerce/reaction-collections";
-const TagSchema = new SimpleSchema([
- Tag,
- {
- catTileImageUrl: {
- type: String,
- defaultValue: "",
- optional: true
- },
- catHeroImageUrl: {
- type: String,
- defaultValue: "",
- optional: true
- },
- catHeroSloganI18nKey: {
- type: String,
- defaultValue: "",
- optional: true
- },
- catHeroTitleI18nKey: {
- type: String,
- defaultValue: "",
- optional: true
- }
+const TagSchema = Tag.clone().extend({
+ catTileImageUrl: {
+ type: String,
+ defaultValue: "",
+ optional: true
+ },
+ catHeroImageUrl: {
+ type: String,
+ defaultValue: "",
+ optional: true
+ },
+ catHeroSloganI18nKey: {
+ type: String,
+ defaultValue: "",
+ optional: true
+ },
+ catHeroTitleI18nKey: {
+ type: String,
+ defaultValue: "",
+ optional: true
}
-]);
+});
Tags.attachSchema(TagSchema, { replace: true });
registerSchema("Tag", TagSchema);
diff --git a/package-lock.json b/package-lock.json
index 06c3474..2abc2b0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,1935 @@
{
"name": "reaction-swag-shop",
"version": "0.0.1",
- "lockfileVersion": 1
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.42.tgz",
+ "integrity": "sha512-L8i94FLSyaLQpRfDo/qqSm8Ndb44zMtXParXo0MebJICG1zoCCL4+GkzUOlB4BNTRSXXQdb3feam/qw7bKPipQ==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "7.0.0-beta.42"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.42.tgz",
+ "integrity": "sha512-9x3zS4nG/6GAvJWB8fAK+5g/Di36xdubB43dMNSucNJTwPvmyfCippir/0I8zyG+ID66hLCLi8V9bomlWRYaHA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "7.0.0-beta.42",
+ "jsesc": "2.5.1",
+ "lodash": "4.17.5",
+ "source-map": "0.5.7",
+ "trim-right": "1.0.1"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.42.tgz",
+ "integrity": "sha512-6IZ+kkPypwJrnmNzI3y31qAps2kXoPtCE241SvBva2YzB0n/YORWx2YM0jHPYOJBU9Xx5KkUhOKuWkeXZQgtTA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "7.0.0-beta.42",
+ "@babel/template": "7.0.0-beta.42",
+ "@babel/types": "7.0.0-beta.42"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.42.tgz",
+ "integrity": "sha512-hF5KKcn+V/5PwU7KZ1aVwo535woLC9eV+djaoyNPZeMMJ2s+8bZlEa66Tarei0T68VRL5LXIs1Ao4hSabSkpBg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "7.0.0-beta.42"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.42.tgz",
+ "integrity": "sha512-2r8pZG6SAJTTaI2OhxCmz5PKlMUPY5adOHrHtb1gM3ibJPDOzPAeOQNzItdxNnM33jjRakEGitXX6iYg7Sz73w==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "7.0.0-beta.42"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.42.tgz",
+ "integrity": "sha512-X3Ur/A/lIbbP8W0pmwgqtDXIxhQmxPaiwY9SKP7kF9wvZfjZRwMvbJE92ozUhF3UDK3DCKaV7oGqmI1rP/zqWA==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.2",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ }
+ },
+ "@babel/template": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.42.tgz",
+ "integrity": "sha512-EK7YdTe47j4VxlwNvz5bnlk5Jx/wWublnqfgOY2IuSNdxCQgXrLD34PfTnabGxywNSkJkcSo6jwr2JGT+S48dA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.0.0-beta.42",
+ "@babel/types": "7.0.0-beta.42",
+ "babylon": "7.0.0-beta.42",
+ "lodash": "4.17.5"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.42.tgz",
+ "integrity": "sha512-DZwMuZBfYVIn/cxpXZzHDgKmarW/MWqplLv1k7QJYhK5r5l6GAac/DkKl75A0CjPYrD3VGco6H6ZQp12QaYKSw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.0.0-beta.42",
+ "@babel/generator": "7.0.0-beta.42",
+ "@babel/helper-function-name": "7.0.0-beta.42",
+ "@babel/helper-split-export-declaration": "7.0.0-beta.42",
+ "@babel/types": "7.0.0-beta.42",
+ "babylon": "7.0.0-beta.42",
+ "debug": "3.1.0",
+ "globals": "11.3.0",
+ "invariant": "2.2.4",
+ "lodash": "4.17.5"
+ }
+ },
+ "@babel/types": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.42.tgz",
+ "integrity": "sha512-+pmpISmTHQqMMpHHtDLxcvtRhmn53bAxy8goJfHipS/uy/r3PLcuSdPizLW7DhtBWbtgIKZufLObfnIMoyMNsw==",
+ "dev": true,
+ "requires": {
+ "esutils": "2.0.2",
+ "lodash": "4.17.5",
+ "to-fast-properties": "2.0.0"
+ }
+ },
+ "@reactioncommerce/eslint-config": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@reactioncommerce/eslint-config/-/eslint-config-1.0.1.tgz",
+ "integrity": "sha512-Lpq/k4UzyUDyXeysZT+o+VMNi8BUTVoM+IfdvYL+7mpNiGYhj3BCprapOZget1t7V11TIxbxSL2wTXvRFP5JaQ==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
+ "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "dev": true,
+ "requires": {
+ "acorn": "3.3.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+ "dev": true
+ }
+ }
+ },
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "dev": true,
+ "requires": {
+ "co": "4.6.0",
+ "fast-deep-equal": "1.1.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
+ "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "1.0.3"
+ }
+ },
+ "aria-query": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.7.1.tgz",
+ "integrity": "sha1-Jsu1r/ZBRLCoJb4YRuCxbPoAsR4=",
+ "dev": true,
+ "requires": {
+ "ast-types-flow": "0.0.7",
+ "commander": "2.15.0"
+ }
+ },
+ "array-includes": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
+ "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
+ "dev": true,
+ "requires": {
+ "define-properties": "1.1.2",
+ "es-abstract": "1.10.0"
+ }
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "1.0.3"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+ "dev": true
+ },
+ "ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
+ "dev": true
+ },
+ "axobject-query": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz",
+ "integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=",
+ "dev": true,
+ "requires": {
+ "ast-types-flow": "0.0.7"
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ }
+ }
+ },
+ "babel-eslint": {
+ "version": "8.2.2",
+ "resolved": "http://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz",
+ "integrity": "sha512-Qt2lz2egBxNYWqN9JIO2z4NOOf8i4b5JS6CFoYrOZZTDssueiV1jH/jsefyg+86SeNY3rB361/mi3kE1WK2WYQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.0.0-beta.42",
+ "@babel/traverse": "7.0.0-beta.42",
+ "@babel/types": "7.0.0-beta.42",
+ "babylon": "7.0.0-beta.42",
+ "eslint-scope": "3.7.1",
+ "eslint-visitor-keys": "1.0.0"
+ }
+ },
+ "babylon": {
+ "version": "7.0.0-beta.42",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz",
+ "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-stream-reader": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-stream-reader/-/buffer-stream-reader-0.1.1.tgz",
+ "integrity": "sha1-yov5NjHe7di4+MO7RJkcwwlR4lk="
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "caller-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "dev": true,
+ "requires": {
+ "callsites": "0.2.0"
+ }
+ },
+ "callsites": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
+ "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.1",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "5.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "supports-color": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz",
+ "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==",
+ "dev": true,
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "chardet": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
+ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
+ "dev": true
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "2.0.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.0.tgz",
+ "integrity": "sha512-7B1ilBwtYSbetCgTY1NJFg+gVpestg0fdA1MhC1Vs4ssyfSXnCAjFr+QcQM9/RedXC0EaUx1sG8Smgw2VfgKEg==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-stream": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz",
+ "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.5",
+ "typedarray": "0.0.6"
+ }
+ },
+ "contains-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
+ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
+ "dev": true
+ },
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.1.2",
+ "shebang-command": "1.2.0",
+ "which": "1.3.0"
+ }
+ },
+ "damerau-levenshtein": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
+ "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
+ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
+ "dev": true,
+ "requires": {
+ "foreach": "2.0.5",
+ "object-keys": "1.0.11"
+ }
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "dev": true,
+ "requires": {
+ "globby": "5.0.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.0",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "rimraf": "2.6.2"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "2.0.2"
+ }
+ },
+ "emoji-regex": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz",
+ "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "0.4.19"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz",
+ "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "1.1.1",
+ "function-bind": "1.1.1",
+ "has": "1.0.1",
+ "is-callable": "1.1.3",
+ "is-regex": "1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
+ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
+ "dev": true,
+ "requires": {
+ "is-callable": "1.1.3",
+ "is-date-object": "1.0.1",
+ "is-symbol": "1.0.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint": {
+ "version": "4.18.2",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz",
+ "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.5.2",
+ "babel-code-frame": "6.26.0",
+ "chalk": "2.3.2",
+ "concat-stream": "1.6.1",
+ "cross-spawn": "5.1.0",
+ "debug": "3.1.0",
+ "doctrine": "2.1.0",
+ "eslint-scope": "3.7.1",
+ "eslint-visitor-keys": "1.0.0",
+ "espree": "3.5.4",
+ "esquery": "1.0.0",
+ "esutils": "2.0.2",
+ "file-entry-cache": "2.0.0",
+ "functional-red-black-tree": "1.0.1",
+ "glob": "7.1.2",
+ "globals": "11.3.0",
+ "ignore": "3.3.7",
+ "imurmurhash": "0.1.4",
+ "inquirer": "3.3.0",
+ "is-resolvable": "1.1.0",
+ "js-yaml": "3.11.0",
+ "json-stable-stringify-without-jsonify": "1.0.1",
+ "levn": "0.3.0",
+ "lodash": "4.17.5",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "natural-compare": "1.4.0",
+ "optionator": "0.8.2",
+ "path-is-inside": "1.0.2",
+ "pluralize": "7.0.0",
+ "progress": "2.0.0",
+ "require-uncached": "1.0.3",
+ "semver": "5.5.0",
+ "strip-ansi": "4.0.0",
+ "strip-json-comments": "2.0.1",
+ "table": "4.0.2",
+ "text-table": "0.2.0"
+ }
+ },
+ "eslint-import-resolver-meteor": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-meteor/-/eslint-import-resolver-meteor-0.4.0.tgz",
+ "integrity": "sha1-yGhjhAghIIz4EzxczlGQnCamFWk=",
+ "dev": true,
+ "requires": {
+ "object-assign": "4.1.1",
+ "resolve": "1.5.0"
+ }
+ },
+ "eslint-import-resolver-node": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
+ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "resolve": "1.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "eslint-module-utils": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz",
+ "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "pkg-dir": "1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-import": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz",
+ "integrity": "sha1-JgAu+/ylmJtyiKwEdQi9JPIXsWk=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "1.1.1",
+ "contains-path": "0.1.0",
+ "debug": "2.6.9",
+ "doctrine": "1.5.0",
+ "eslint-import-resolver-node": "0.3.2",
+ "eslint-module-utils": "2.1.1",
+ "has": "1.0.1",
+ "lodash": "4.17.5",
+ "minimatch": "3.0.4",
+ "read-pkg-up": "2.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+ "dev": true,
+ "requires": {
+ "esutils": "2.0.2",
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-jest": {
+ "version": "21.15.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-21.15.0.tgz",
+ "integrity": "sha512-Qe1egBnn0obmFQ9quZiJwwsf1H6oBXrJBku7OUt8XdCSwKL6h7xC4OKyg2px9jQXxv7YcTNUIFAGk2OUpPfDOA==",
+ "dev": true
+ },
+ "eslint-plugin-jsx-a11y": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.0.3.tgz",
+ "integrity": "sha1-VFg9GuRCSDFi4EDhPMMYZUZRAOU=",
+ "dev": true,
+ "requires": {
+ "aria-query": "0.7.1",
+ "array-includes": "3.0.3",
+ "ast-types-flow": "0.0.7",
+ "axobject-query": "0.1.0",
+ "damerau-levenshtein": "1.0.4",
+ "emoji-regex": "6.5.1",
+ "jsx-ast-utils": "2.0.1"
+ }
+ },
+ "eslint-plugin-react": {
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz",
+ "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==",
+ "dev": true,
+ "requires": {
+ "doctrine": "2.1.0",
+ "has": "1.0.1",
+ "jsx-ast-utils": "2.0.1",
+ "prop-types": "15.6.1"
+ }
+ },
+ "eslint-scope": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+ "dev": true,
+ "requires": {
+ "esrecurse": "4.2.1",
+ "estraverse": "4.2.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+ "dev": true
+ },
+ "espree": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
+ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
+ "dev": true,
+ "requires": {
+ "acorn": "5.5.3",
+ "acorn-jsx": "3.0.1"
+ }
+ },
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz",
+ "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=",
+ "dev": true,
+ "requires": {
+ "estraverse": "4.2.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "dev": true,
+ "requires": {
+ "estraverse": "4.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "external-editor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz",
+ "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==",
+ "dev": true,
+ "requires": {
+ "chardet": "0.4.2",
+ "iconv-lite": "0.4.19",
+ "tmp": "0.0.33"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fbjs": {
+ "version": "0.8.16",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz",
+ "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=",
+ "dev": true,
+ "requires": {
+ "core-js": "1.2.7",
+ "isomorphic-fetch": "2.2.1",
+ "loose-envify": "1.3.1",
+ "object-assign": "4.1.1",
+ "promise": "7.3.1",
+ "setimmediate": "1.0.5",
+ "ua-parser-js": "0.7.17"
+ }
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "dev": true,
+ "requires": {
+ "flat-cache": "1.3.0",
+ "object-assign": "4.1.1"
+ }
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "flat-cache": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "dev": true,
+ "requires": {
+ "circular-json": "0.3.3",
+ "del": "2.2.2",
+ "graceful-fs": "4.1.11",
+ "write": "0.2.1"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "globals": {
+ "version": "11.3.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz",
+ "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==",
+ "dev": true
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "1.0.2",
+ "arrify": "1.0.1",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
+ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
+ "dev": true,
+ "requires": {
+ "function-bind": "1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
+ "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
+ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
+ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "3.0.0",
+ "chalk": "2.3.2",
+ "cli-cursor": "2.1.0",
+ "cli-width": "2.2.0",
+ "external-editor": "2.1.0",
+ "figures": "2.0.0",
+ "lodash": "4.17.5",
+ "mute-stream": "0.0.7",
+ "run-async": "2.3.0",
+ "rx-lite": "4.0.8",
+ "rx-lite-aggregates": "4.0.8",
+ "string-width": "2.1.1",
+ "strip-ansi": "4.0.0",
+ "through": "2.3.8"
+ }
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "1.1.1"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
+ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
+ "dev": true
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
+ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "1.0.1"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "1.0.2"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "1.0.1"
+ }
+ },
+ "is-resolvable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
+ "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "dev": true,
+ "requires": {
+ "node-fetch": "1.7.3",
+ "whatwg-fetch": "2.0.3"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
+ "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.10",
+ "esprima": "4.0.0"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
+ "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "jsx-ast-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
+ "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
+ "dev": true,
+ "requires": {
+ "array-includes": "3.0.3"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2"
+ }
+ },
+ "load-json-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "strip-bom": "3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "2.0.0",
+ "path-exists": "3.0.0"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
+ "dev": true,
+ "requires": {
+ "js-tokens": "3.0.2"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz",
+ "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.11"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "dev": true,
+ "requires": {
+ "encoding": "0.1.12",
+ "is-stream": "1.1.0"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "2.6.0",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.5.0",
+ "validate-npm-package-license": "3.0.3"
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
+ "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "1.2.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "0.1.3",
+ "fast-levenshtein": "2.0.6",
+ "levn": "0.3.0",
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2",
+ "wordwrap": "1.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
+ "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==",
+ "dev": true,
+ "requires": {
+ "p-try": "1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "1.2.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "1.3.1"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
+ "dev": true
+ },
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "dev": true,
+ "requires": {
+ "pify": "2.3.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "2.0.4"
+ }
+ },
+ "pkg-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
+ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2"
+ }
+ },
+ "pluralize": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+ "dev": true
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dev": true,
+ "requires": {
+ "asap": "2.0.6"
+ }
+ },
+ "prop-types": {
+ "version": "15.6.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz",
+ "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==",
+ "dev": true,
+ "requires": {
+ "fbjs": "0.8.16",
+ "loose-envify": "1.3.1",
+ "object-assign": "4.1.1"
+ }
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "2.0.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "dev": true,
+ "requires": {
+ "find-up": "2.1.0",
+ "read-pkg": "2.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "2.0.0"
+ }
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz",
+ "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "require-uncached": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "dev": true,
+ "requires": {
+ "caller-path": "0.1.0",
+ "resolve-from": "1.0.1"
+ }
+ },
+ "resolve": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
+ "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
+ "dev": true,
+ "requires": {
+ "path-parse": "1.0.5"
+ }
+ },
+ "resolve-from": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "2.0.1",
+ "signal-exit": "3.0.2"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "dev": true,
+ "requires": {
+ "is-promise": "2.1.0"
+ }
+ },
+ "rx-lite": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
+ "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
+ "dev": true
+ },
+ "rx-lite-aggregates": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
+ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "dev": true,
+ "requires": {
+ "rx-lite": "4.0.8"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "dev": true
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+ "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "3.0.0",
+ "spdx-license-ids": "3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+ "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "2.1.0",
+ "spdx-license-ids": "3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
+ "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "table": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
+ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.5.2",
+ "ajv-keywords": "2.1.1",
+ "chalk": "2.3.2",
+ "lodash": "4.17.5",
+ "slice-ansi": "1.0.0",
+ "string-width": "2.1.1"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "ua-parser-js": {
+ "version": "0.7.17",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
+ "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
+ "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "3.0.0",
+ "spdx-expression-parse": "3.0.0"
+ }
+ },
+ "whatwg-fetch": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
+ "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "dev": true,
+ "requires": {
+ "mkdirp": "0.5.1"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
}
diff --git a/package.json b/package.json
index b5debf1..ed72ae3 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,8 @@
"description": "A Reaction Commerce plugin that creates swagshop.reactioncommerce.com",
"main": "register.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "lint": "eslint ."
},
"repository": {
"type": "git",
@@ -22,6 +23,9 @@
"url": "https://github.com/reactioncommerce/reaction-swag-shop/issues"
},
"homepage": "https://github.com/reactioncommerce/reaction-swag-shop#readme",
+ "dependencies": {
+ "buffer-stream-reader": "^0.1.1"
+ },
"babel": {
"plugins": [
[
@@ -54,5 +58,18 @@
"react",
"stage-2"
]
+ },
+ "eslintConfig": {
+ "extends": "@reactioncommerce"
+ },
+ "devDependencies": {
+ "eslint-import-resolver-meteor": "^0.4.0",
+ "babel-eslint": "^8.2.1",
+ "@reactioncommerce/eslint-config": "^1.0.1",
+ "eslint": "^4.17.0",
+ "eslint-plugin-import": "^2.8.0",
+ "eslint-plugin-jsx-a11y": "^6.0.3",
+ "eslint-plugin-react": "^7.6.1",
+ "eslint-plugin-jest": "^21.14.0"
}
}
diff --git a/server/index.js b/server/index.js
index 1cac50d..e11f0cd 100644
--- a/server/index.js
+++ b/server/index.js
@@ -1,6 +1,5 @@
-// Use custom schemas
import "../lib/collections/schemas";
-import "./init";
import "./publications";
+import "./init";
import "./requestApproachFromStaff";
import "./register.js";
diff --git a/server/init.js b/server/init.js
index 1180294..0f91946 100644
--- a/server/init.js
+++ b/server/init.js
@@ -13,11 +13,12 @@ Hooks.Events.add("beforeCoreInit", () => {
Hooks.Events.add("afterCoreInit", () => {
methods.initLayout();
methods.loadProducts();
+ methods.importProductImages();
+ methods.publishProducts();
methods.loadTags();
methods.loadShipping();
methods.enableShipping();
methods.enablePayment();
- methods.importProductImages();
methods.setupRoutes();
Logger.info("Finished loading the rest of the Demo data");
});
diff --git a/server/methods.js b/server/methods.js
index c439eb5..2a0fc9d 100644
--- a/server/methods.js
+++ b/server/methods.js
@@ -1,6 +1,9 @@
import { Meteor } from "meteor/meteor";
import { check } from "meteor/check";
-import { Shops, Products, Tags, Shipping, Media, Packages } from "/lib/collections";
+import bufferStreamReader from "buffer-stream-reader";
+import { FileRecord } from "@reactioncommerce/file-collections";
+import { Shops, Products, Tags, Shipping, MediaRecords, Packages, Catalog } from "/lib/collections";
+import { Media } from "/imports/plugins/core/files/server";
import { Logger, Reaction } from "/server/api";
function checkForShops() {
@@ -24,10 +27,41 @@ function checkForShipping() {
}
function checkForMedia() {
- const numMedia = Media.find().count();
+ const numMedia = MediaRecords.find().count();
return numMedia !== 0;
}
+function checkForCatalog() {
+ const numCatalog = Catalog.find().count();
+ return numCatalog !== 0;
+}
+
+async function storeFromAttachedBuffer(fileRecord) {
+ const { stores } = fileRecord.collection.options;
+ const bufferData = fileRecord.data;
+
+ // We do these in series to avoid issues with multiple streams reading
+ // from the temp store at the same time.
+ try {
+ for (const store of stores) {
+ if (fileRecord.hasStored(store.name)) {
+ return Promise.resolve();
+ }
+
+ // Make a new read stream in each loop because you can only read once
+ const readStream = new bufferStreamReader(bufferData);
+ const writeStream = await store.createWriteStream(fileRecord); // eslint-disable-line no-await-in-loop
+ await new Promise((resolve, reject) => { // eslint-disable-line no-await-in-loop
+ fileRecord.once("error", reject);
+ fileRecord.once("stored", resolve);
+ readStream.pipe(writeStream);
+ });
+ }
+ } catch (error) {
+ throw new Error("Error in storeFromAttachedBuffer:", error);
+ }
+}
+
const methods = {};
methods.loadShops = function () {
@@ -58,6 +92,16 @@ methods.loadProducts = function () {
}
};
+methods.publishProducts = function () {
+ if (!checkForCatalog()) {
+ const userId = Meteor.users.findOne({ name: "Admin" })._id;
+ const productIds = Products.find({ type: "simple" }).map((doc) => doc._id);
+ Meteor.runAsUser(userId, () => {
+ Meteor.call("catalog/publish/products", productIds);
+ });
+ }
+};
+
methods.loadTags = function () {
if (!checkForTags()) {
Logger.info("Starting load Tags");
@@ -97,7 +141,7 @@ methods.initLayout = function () {
const layout = require("../private/data/Layout.json");
const shopId = Reaction.getShopId();
return Shops.update(shopId, {
- $set: { layout: layout }
+ $set: { layout }
});
};
@@ -124,23 +168,31 @@ methods.importProductImages = function () {
const products = Products.find({ type: "simple" }).fetch();
for (const product of products) {
const productId = product._id;
- if (!Media.findOne({ "metadata.productId": productId })) {
- const shopId = product.shopId;
+ if (!MediaRecords.findOne({ "metadata.productId": productId })) {
+ const { shopId } = product;
const filepath = `plugins/reaction-swag-shop/images/${productId}.jpg`;
- const binary = Assets.getBinary(filepath);
- const fileObj = new FS.File();
- const fileName = `${productId}.jpg`;
- fileObj.attachData(binary, { type: "image/jpeg", name: fileName });
+ const uint8array = Assets.getBinary(filepath);
const topVariant = getTopVariant(productId);
- fileObj.metadata = {
- productId: productId,
+
+ const metadata = {
+ productId,
variantId: topVariant._id,
toGrid: 1,
- shopId: shopId,
+ shopId,
priority: 0,
workflow: "published"
};
- Media.insert(fileObj);
+ const fileRecord = new FileRecord({
+ original: {
+ size: uint8array.length,
+ name: `${productId}.jpg`,
+ type: "image/jpeg"
+ }
+ });
+ fileRecord.attachData(new Buffer(uint8array));
+ fileRecord.metadata = metadata;
+ Media.insert(fileRecord);
+ Promise.await(storeFromAttachedBuffer(fileRecord));
}
}
Logger.info("loaded product images");
@@ -158,7 +210,7 @@ methods.setupRoutes = function () {
{
$set:
{
- "registry.$.template": "categoryGrid"
+ "registry.$.template": "ProductsCustomer"
}
}
);
diff --git a/server/publications/collections/products.js b/server/publications/collections/products.js
index 216f469..e4e500c 100644
--- a/server/publications/collections/products.js
+++ b/server/publications/collections/products.js
@@ -1,65 +1,23 @@
import _ from "lodash";
import { Meteor } from "meteor/meteor";
import { check, Match } from "meteor/check";
-import { Products, Shops, Revisions } from "/lib/collections";
-import { Reaction, Logger } from "/server/api";
-import { RevisionApi } from "/imports/plugins/core/revisions/lib/api/revisions";
-import { findProductMedia } from "/server/publications/collections/product";
+import { Shops, Tags, Catalog } from "/lib/collections";
+import { Logger } from "/server/api";
import { getSchemas } from "@reactioncommerce/reaction-collections";
// Validate the subscription filter against our extended filter schema.
const Schemas = getSchemas();
-const filters = Schemas.filters;
-
-/* Replace stock publication with our custom publication that knows how to filter
- * featured products as well.
- */
-Meteor.startup(() => {
- Meteor.default_server.publish_handlers.Products = publishFeaturedSwagProducts;
-});
-
-/**
- * Swag shop products publication. Knows how to filter for featured products.
- * @param {Number} [productScrollLimit] - optional, defaults to 24
- * @param {Array} shops - array of shopId to retrieve product from.
- * @return {Object} return product cursor
- */
-function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, sort = {}, editMode = true) {
- check(productScrollLimit, Number);
- check(productFilters, Match.OneOf(undefined, Object));
- check(sort, Match.OneOf(undefined, Object));
- check(editMode, Match.Maybe(Boolean));
-
- // TODO: Consider publishing the non-admin publication if a user is not in "edit mode" to see what is published
-
- // Active shop
- const shopId = Reaction.getShopId();
- const primaryShopId = Reaction.getPrimaryShopId();
-
- // Get a list of shopIds that this user has "createProduct" permissions for (owner permission is checked by default)
- const userAdminShopIds = Reaction.getShopsWithRoles(["createProduct"], this.userId);
-
- // Don't publish if we're missing an active or primary shopId
- if (!shopId || !primaryShopId) {
- return this.ready();
- }
-
- // Get active shop id's to use for filtering
- const activeShopsIds = Shops.find({
- $or: [
- { "workflow.status": "active" },
- { _id: Reaction.getPrimaryShopId() }
- ]
- }).fetch().map(activeShop => activeShop._id);
+const { filters } = Schemas;
+function filterProducts(productFilters) {
// if there are filter/params that don't match the schema
// validate, catch except but return no results
try {
- check(productFilters, Match.OneOf(undefined, filters));
+ if (productFilters) filters.validate(productFilters);
} catch (e) {
Logger.debug(e, "Invalid Product Filters");
- return this.ready();
+ return false;
}
const shopIdsOrSlugs = productFilters && productFilters.shops;
@@ -67,14 +25,11 @@ function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, so
if (shopIdsOrSlugs) {
// Get all shopIds associated with the slug or Id
const shopIds = Shops.find({
- $or: [{
- _id: {
- $in: shopIdsOrSlugs
- }
+ "workflow.status": "active",
+ "$or": [{
+ _id: { $in: shopIdsOrSlugs }
}, {
- slug: {
- $in: shopIdsOrSlugs
- }
+ slug: { $in: shopIdsOrSlugs }
}]
}).map((shop) => shop._id);
@@ -82,7 +37,7 @@ function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, so
if (shopIds) {
productFilters.shops = shopIds;
} else {
- return this.ready();
+ return false;
}
}
@@ -97,15 +52,9 @@ function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, so
// handle multiple shops
if (productFilters.shops) {
_.extend(selector, {
- $or: [{
- shopId: {
- $in: productFilters.shops
- }
- }, {
- slug: {
- $in: productFilters.shops
- }
- }]
+ shopId: {
+ $in: productFilters.shops
+ }
});
}
@@ -224,9 +173,8 @@ function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, so
}
});
}
-
// BOF: swag shop featuredProduct filter
- if (productFilters.hasOwnProperty("featuredProductLabel")) {
+ if (Object.prototype.hasOwnProperty.call(productFilters, "featuredProductLabel")) {
if (productFilters.featuredProductLabel !== "") {
_.extend(selector, {
// Return only featured products that match the label exactly
@@ -241,280 +189,56 @@ function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, so
});
}
}
- // EOF: swag shop featuredProduct filter
- } // end if productFilters
-
- // We publish an admin version of this publication to admins of products who are in "Edit Mode"
- // Authorized content curators for shops get special publication of the product
- // with all relevant revisions all is one package
- // userAdminShopIds is a list of shopIds that the user has createProduct or owner access for
- if (editMode && userAdminShopIds && Array.isArray(userAdminShopIds) && userAdminShopIds.length > 0) {
- selector.isVisible = {
- $in: [true, false, null, undefined]
- };
- selector.shopId = {
- $in: activeShopsIds
- };
-
- // Get _ids of top-level products
- const productIds = Products.find(selector, {
- sort: sort,
- limit: productScrollLimit
- }).map(product => product._id);
-
- let newSelector = selector;
-
- // Remove hashtag filter from selector (hashtags are not applied to variants, we need to get variants)
- if (productFilters && productFilters.tags) {
- newSelector = _.omit(selector, ["hashtags", "ancestors"]);
-
- // Re-configure selector to pick either Variants of one of the top-level products, or the top-level products in the filter
- _.extend(newSelector, {
- $or: [{
- ancestors: {
- $in: productIds
- }
- }, {
- $and: [{
- hashtags: {
- $in: productFilters.tags
- }
- }, {
- _id: {
- $in: productIds
- }
- }]
- }]
- });
- } else {
- newSelector = _.omit(selector, ["hashtags", "ancestors"]);
- _.extend(newSelector, {
- $or: [{
- ancestors: {
- $in: productIds
- }
- }, {
- _id: {
- $in: productIds
- }
- }]
- });
- }
-
- if (RevisionApi.isRevisionControlEnabled()) {
- const productCursor = Products.find(newSelector);
- const handle = productCursor.observeChanges({
- added: (id, fields) => {
- const revisions = Revisions.find({
- "$or": [
- { documentId: id },
- { parentDocument: id }
- ],
- "workflow.status": {
- $nin: [
- "revision/published"
- ]
- }
- }).fetch();
- fields.__revisions = revisions;
-
- this.added("Products", id, fields);
- },
- changed: (id, fields) => {
- const revisions = Revisions.find({
- "$or": [
- { documentId: id },
- { parentDocument: id }
- ],
- "workflow.status": {
- $nin: [
- "revision/published"
- ]
- }
- }).fetch();
-
- fields.__revisions = revisions;
- this.changed("Products", id, fields);
- },
- removed: (id) => {
- this.removed("Products", id);
- }
- });
-
- const handle2 = Revisions.find({
- "workflow.status": {
- $nin: [
- "revision/published"
- ]
+ if (Object.prototype.hasOwnProperty.call(productFilters, "relatedTag")) {
+ if (productFilters.relatedTag !== "") {
+ const tag = Tags.findOne({ name: productFilters.relatedTag });
+ if (tag) {
+ _.extend(selector, {
+ hashtags: tag._id,
+ ancestors: { $size: 0 }
+ });
}
- }).observe({
- added: (revision) => {
- let product;
- if (!revision.documentType || revision.documentType === "product") {
- product = Products.findOne(revision.documentId);
- } else if (revision.documentType === "image" || revision.documentType === "tag") {
- product = Products.findOne(revision.parentDocument);
- }
-
- if (product) {
- this.added("Products", product._id, product);
- this.added("Revisions", revision._id, revision);
- }
- },
- changed: (revision) => {
- let product;
- if (!revision.documentType || revision.documentType === "product") {
- product = Products.findOne(revision.documentId);
- } else if (revision.documentType === "image" || revision.documentType === "tag") {
- product = Products.findOne(revision.parentDocument);
- }
- if (product) {
- product.__revisions = [revision];
- this.changed("Products", product._id, product);
- this.changed("Revisions", revision._id, revision);
- }
- },
- removed: (revision) => {
- let product;
-
- if (!revision.documentType || revision.documentType === "product") {
- product = Products.findOne(revision.documentId);
- } else if (revision.docuentType === "image" || revision.documentType === "tag") {
- product = Products.findOne(revision.parentDocument);
- }
- if (product) {
- product.__revisions = [];
- this.changed("Products", product._id, product);
- this.removed("Revisions", revision._id, revision);
- }
- }
- });
-
-
- this.onStop(() => {
- handle.stop();
- handle2.stop();
- });
-
- const mediaProductIds = productCursor.fetch().map((p) => p._id);
- const mediaCursor = findProductMedia(this, mediaProductIds);
-
- return [
- mediaCursor
- ];
+ }
}
- // Revision control is disabled, but is admin
- const productCursor = Products.find(newSelector, {
- sort: sort,
- limit: productScrollLimit
- });
- const mediaProductIds = productCursor.fetch().map((p) => p._id);
- const mediaCursor = findProductMedia(this, mediaProductIds);
+ // EOF: swag shop featuredProduct filter
+ } // end if productFilters
- return [
- productCursor,
- mediaCursor
- ];
- }
+ return selector;
+}
- // This is where the publication begins for non-admin users
- // Get _ids of top-level products
- const productIds = Products.find(selector, {
- sort: sort,
- limit: productScrollLimit
- }).map(product => product._id);
+/* Replace stock publication with our custom publication that knows how to filter
+ * featured products as well.
+ */
+Meteor.startup(() => {
+ Meteor.default_server.publish_handlers["Products/grid"] = publishFeaturedSwagProducts;
+});
- let newSelector = { ...selector };
- // Remove hashtag filter from selector (hashtags are not applied to variants, we need to get variants)
- if (productFilters && Object.keys(productFilters).length === 0 && productFilters.constructor === Object) {
- newSelector = _.omit(selector, ["hashtags", "ancestors"]);
+/**
+ * Swag shop products publication. Knows how to filter for featured products.
+ * @param {Number} [productScrollLimit] - optional, defaults to 24
+ * @param {Array} shops - array of shopId to retrieve product from.
+ * @return {Object} return product cursor
+ */
+function publishFeaturedSwagProducts(productScrollLimit = 24, productFilters, sort = {}) {
+ check(productScrollLimit, Number);
+ check(productFilters, Match.OneOf(undefined, Object));
+ check(sort, Match.OneOf(undefined, Object));
- if (productFilters.tags) {
- // Re-configure selector to pick either Variants of one of the top-level products,
- // or the top-level products in the filter
- _.extend(newSelector, {
- $or: [{
- ancestors: {
- $in: productIds
- }
- }, {
- $and: [{
- hashtags: {
- $in: productFilters.tags
- }
- }, {
- _id: {
- $in: productIds
- }
- }]
- }]
- });
- }
- // filter by query
- if (productFilters.query) {
- const cond = {
- $regex: productFilters.query,
- $options: "i"
- };
- _.extend(newSelector, {
- $or: [{
- title: cond
- }, {
- pageTitle: cond
- }, {
- description: cond
- }, {
- ancestors: {
- $in: productIds
- }
- },
- {
- _id: {
- $in: productIds
- }
- }]
- });
- }
- } else {
- newSelector = _.omit(selector, ["hashtags", "ancestors"]);
+ const newSelector = filterProducts(productFilters);
- _.extend(newSelector, {
- $or: [{
- ancestors: {
- $in: productIds
- }
- }, {
- _id: {
- $in: productIds
- }
- }]
- });
+ if (newSelector === false) {
+ return this.ready();
}
- // Adjust the selector to include only active shops
- newSelector = {
- ...newSelector,
- shopId: {
- $in: activeShopsIds
+ const productCursor = Catalog.find(newSelector, {
+ sort,
+ limit: productScrollLimit,
+ fields: {
+ variants: 0
}
- };
-
- // Returning Complete product tree for top level products to avoid sold out warning.
- const productCursor = Products.find(newSelector, {
- sort: sort
- // TODO: REVIEW Limiting final products publication for non-admins
- // I think we shouldn't limit here, otherwise we are limited to 24 total products which
- // could be far less than 24 top-level products
- // limit: productScrollLimit
});
- const mediaProductIds = productCursor.fetch().map((p) => p._id);
- const mediaCursor = findProductMedia(this, mediaProductIds);
-
- return [
- productCursor,
- mediaCursor
- ];
+ return productCursor;
}
diff --git a/server/publications/collections/schemas/filters.js b/server/publications/collections/schemas/filters.js
new file mode 100644
index 0000000..cdd4ea2
--- /dev/null
+++ b/server/publications/collections/schemas/filters.js
@@ -0,0 +1,15 @@
+import { getSchemas, registerSchema } from "@reactioncommerce/reaction-collections";
+
+const Schemas = getSchemas();
+const ExtendedFilters = Schemas.filters.clone().extend({
+ featuredProductLabel: {
+ type: String,
+ optional: true
+ },
+ relatedTag: {
+ type: String,
+ optional: true
+ }
+});
+
+registerSchema("filters", ExtendedFilters);
diff --git a/server/publications/collections/schemas/index.js b/server/publications/collections/schemas/index.js
new file mode 100644
index 0000000..1e83ca0
--- /dev/null
+++ b/server/publications/collections/schemas/index.js
@@ -0,0 +1 @@
+import "./filters";
diff --git a/server/publications/index.js b/server/publications/index.js
index 84fa47c..0758f86 100644
--- a/server/publications/index.js
+++ b/server/publications/index.js
@@ -1 +1,2 @@
-export * from "./collections/products";
+import "./collections/schemas";
+import "./collections/products";
diff --git a/server/requestApproachFromStaff.js b/server/requestApproachFromStaff.js
index 5a519ac..a520735 100644
--- a/server/requestApproachFromStaff.js
+++ b/server/requestApproachFromStaff.js
@@ -7,7 +7,7 @@ const methods = {
"reaction-swag-shop/requestApproachFromStaff": (email) => {
check(email, String);
- Logger.info("contact person at " + email);
+ Logger.info(`Contact person at ${email}`);
}
};