Skip to content

Commit

Permalink
namespace product resource
Browse files Browse the repository at this point in the history
  • Loading branch information
Mina Smart committed Nov 30, 2017
1 parent c205117 commit 8acfa87
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 160 deletions.
115 changes: 4 additions & 111 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import handleCheckoutMutation from './handle-checkout-mutation';
import productHelpers from './product-helpers';
import imageHelpers from './image-helpers';
import defaultResolver from './default-resolver';
import fetchResourcesForProducts from './fetch-resources-for-products';
import {paginateCollectionsProductConnectionsAndResolve} from './paginators';
import ProductResource from './product-resource';
import {version} from '../package.json';

// GraphQL
import types from '../schema.json';
import checkoutNodeQuery from './graphql/checkoutNodeQuery.graphql';
import productNodeQuery from './graphql/productNodeQuery.graphql';
import productConnectionQuery from './graphql/productConnectionQuery.graphql';
import productByHandleQuery from './graphql/productByHandleQuery.graphql';
import collectionNodeQuery from './graphql/collectionNodeQuery.graphql';
import collectionNodeWithProductsQuery from './graphql/collectionNodeWithProductsQuery.graphql';
import collectionConnectionQuery from './graphql/collectionConnectionQuery.graphql';
Expand All @@ -25,26 +23,6 @@ import checkoutLineItemsAddMutation from './graphql/checkoutLineItemsAddMutation
import checkoutLineItemsRemoveMutation from './graphql/checkoutLineItemsRemoveMutation.graphql';
import checkoutLineItemsUpdateMutation from './graphql/checkoutLineItemsUpdateMutation.graphql';

function paginateProductConnectionsAndResolve(client) {
return function(products) {
return fetchResourcesForProducts(products, client).then(() => {
return products;
});
};
}

function paginateCollectionsProductConnectionsAndResolve(client) {
return function(collectionOrCollections) {
const collections = [].concat(collectionOrCollections);

return Promise.all(collections.reduce((promiseAcc, collection) => {
return promiseAcc.concat(fetchResourcesForProducts(collection.products, client));
}, [])).then(() => {
return collectionOrCollections;
});
};
}

/**
* The JS Buy SDK Client.
* @class
Expand Down Expand Up @@ -97,6 +75,8 @@ class Client {
}
}
});

this.product = new ProductResource(this.graphQLClient, productHelpers);
}

/**
Expand Down Expand Up @@ -132,61 +112,6 @@ class Client {
.then(defaultResolver('shop'));
}

/**
* Fetches all products on the shop.
*
* @example
* client.fetchAllProducts().then((products) => {
* // Do something with the products
* });
*
* @param {Client.Queries.productConnectionQuery} [query] Callback function to specify fields to query on the products.
* @return {Promise|GraphModel[]} A promise resolving with an array of `GraphModel`s of the products.
*/
fetchAllProducts(pageSize = 20) {
return this.graphQLClient
.send(productConnectionQuery, {pageSize})
.then(defaultResolver('shop.products'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches a single product by ID on the shop.
*
* @example
* client.fetchProduct('Xk9lM2JkNzFmNzIQ4NTIY4ZDFi9DaGVja291dC9lM2JkN==').then((product) => {
* // Do something with the product
* });
*
* @param {String} id The id of the product to fetch.
* @param {Client.Queries.productNodeQuery} [query] Callback function to specify fields to query on the product.
* @return {Promise|GraphModel} A promise resolving with a `GraphModel` of the product.
*/
fetchProduct(id) {
return this.graphQLClient
.send(productNodeQuery, {id})
.then(defaultResolver('node'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches a single product by handle on the shop.
*
* @example
* client.fetchProductByHandle('my-product').then((product) => {
* // Do something with the product
* });
*
* @param {String} handle The handle of the product to fetch.
* @return {Promise|GraphModel} A promise resolving with a `GraphModel` of the product.
*/
fetchProductByHandle(handle) {
return this.graphQLClient
.send(productByHandleQuery, {handle})
.then(defaultResolver('shop.productByHandle'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches a collection by handle on the shop.
*
Expand Down Expand Up @@ -301,38 +226,6 @@ class Client {
});
}

/**
* Fetches all products on the shop that match the query.
*
* @example
* client.fetchQueryProducts({sortBy: 'title', limit: 10}).then((products) => {
* // Do something with the first 10 products sorted by title in ascending order
* });
*
* @param {Object} [queryObject] An object specifying the query data containing zero or more of:
* @param {String} [queryObject.title] The title of the product to fetch.
* @param {String} [queryObject.updatedAtMin] Products updated since the supplied timestamp (format: `2016-09-25T21:31:33`).
* @param {String} [queryObject.createdAtMin] Products created since the supplied timestamp (format: `2016-09-25T21:31:33`).
* @param {String} [queryObject.productType] The type of products to fetch.
* @param {Number} [queryObject.limit=20] The number of products to fetch.
* @param {String} [queryObject.sortBy] The field to use to sort products. Possible values are `title`, `updatedAt`, and `createdAt`.
* @param {String} [queryObject.sortDirection] The sort direction of the products.
* Will sort products by ascending order unless `'desc'` is specified.
* @param {Client.Queries.productConnectionQuery} [query] Callback function to specify fields to query on the products.
* @return {Promise|GraphModel[]} A promise resolving with an array of `GraphModel`s of the products.
*/
fetchQueryProducts({first = 20, sortKey = 'ID', query, reverse}) {
return this.graphQLClient
.send(productConnectionQuery, {
first,
sortKey: this.graphQLClient.enum(sortKey),
query,
reverse
})
.then(defaultResolver('shop.products'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches all collections on the shop that match the query.
*
Expand Down
21 changes: 21 additions & 0 deletions src/paginators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import fetchResourcesForProducts from './fetch-resources-for-products';

export function paginateProductConnectionsAndResolve(client) {
return function(products) {
return fetchResourcesForProducts(products, client).then(() => {
return products;
});
};
}

export function paginateCollectionsProductConnectionsAndResolve(client) {
return function(collectionOrCollections) {
const collections = [].concat(collectionOrCollections);

return Promise.all(collections.reduce((promiseAcc, collection) => {
return promiseAcc.concat(fetchResourcesForProducts(collection.products, client));
}, [])).then(() => {
return collectionOrCollections;
});
};
}
2 changes: 1 addition & 1 deletion src/product-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
/**
* Returns the variant of a product corresponding to the options given.
*
* @memberof Client.Product.Helpers
* @memberof Client.product.Helpers
* @method variantForOptions
* @param {GraphModel} product The product to find the variant on. Must include `variants`.
* @param {Object} options An object containing the options for the variant.
Expand Down
99 changes: 99 additions & 0 deletions src/product-resource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import Resource from './resource';
import defaultResolver from './default-resolver';
import {paginateProductConnectionsAndResolve} from './paginators';

// GraphQL
import productNodeQuery from './graphql/productNodeQuery.graphql';
import productConnectionQuery from './graphql/productConnectionQuery.graphql';
import productByHandleQuery from './graphql/productByHandleQuery.graphql';

export default class ProductResource extends Resource {

/**
* Fetches all products on the shop.
*
* @example
* client.fetchAllProducts().then((products) => {
* // Do something with the products
* });
*
* @param {Client.Queries.productConnectionQuery} [query] Callback function to specify fields to query on the products.
* @return {Promise|GraphModel[]} A promise resolving with an array of `GraphModel`s of the products.
*/
fetchAll(pageSize = 20) {
return this.graphQLClient
.send(productConnectionQuery, {pageSize})
.then(defaultResolver('shop.products'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches a single product by ID on the shop.
*
* @example
* client.fetchProduct('Xk9lM2JkNzFmNzIQ4NTIY4ZDFi9DaGVja291dC9lM2JkN==').then((product) => {
* // Do something with the product
* });
*
* @param {String} id The id of the product to fetch.
* @param {Client.Queries.productNodeQuery} [query] Callback function to specify fields to query on the product.
* @return {Promise|GraphModel} A promise resolving with a `GraphModel` of the product.
*/
fetch(id) {
return this.graphQLClient
.send(productNodeQuery, {id})
.then(defaultResolver('node'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches a single product by handle on the shop.
*
* @example
* client.fetchProductByHandle('my-product').then((product) => {
* // Do something with the product
* });
*
* @param {String} handle The handle of the product to fetch.
* @return {Promise|GraphModel} A promise resolving with a `GraphModel` of the product.
*/
fetchByHandle(handle) {
return this.graphQLClient
.send(productByHandleQuery, {handle})
.then(defaultResolver('shop.productByHandle'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

/**
* Fetches all products on the shop that match the query.
*
* @example
* client.fetchQueryProducts({sortBy: 'title', limit: 10}).then((products) => {
* // Do something with the first 10 products sorted by title in ascending order
* });
*
* @param {Object} [queryObject] An object specifying the query data containing zero or more of:
* @param {String} [queryObject.title] The title of the product to fetch.
* @param {String} [queryObject.updatedAtMin] Products updated since the supplied timestamp (format: `2016-09-25T21:31:33`).
* @param {String} [queryObject.createdAtMin] Products created since the supplied timestamp (format: `2016-09-25T21:31:33`).
* @param {String} [queryObject.productType] The type of products to fetch.
* @param {Number} [queryObject.limit=20] The number of products to fetch.
* @param {String} [queryObject.sortBy] The field to use to sort products. Possible values are `title`, `updatedAt`, and `createdAt`.
* @param {String} [queryObject.sortDirection] The sort direction of the products.
* Will sort products by ascending order unless `'desc'` is specified.
* @param {Client.Queries.productConnectionQuery} [query] Callback function to specify fields to query on the products.
* @return {Promise|GraphModel[]} A promise resolving with an array of `GraphModel`s of the products.
*/
fetchQuery({first = 20, sortKey = 'ID', query, reverse}) {
return this.graphQLClient
.send(productConnectionQuery, {
first,
sortKey: this.graphQLClient.enum(sortKey),
query,
reverse
})
.then(defaultResolver('shop.products'))
.then(paginateProductConnectionsAndResolve(this.graphQLClient));
}

}
6 changes: 6 additions & 0 deletions src/resource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default class Resource {
constructor(client, helpers) {
this.graphQLClient = client;
this.helpers = helpers;
}
}
Loading

0 comments on commit 8acfa87

Please sign in to comment.