Merge branch 'master' of github.com:okbel/e-comm-example

This commit is contained in:
Belen Curcio 2020-09-30 10:52:08 -03:00
commit 97dd5abc30
13 changed files with 5986 additions and 153 deletions

24
codegen.json Normal file
View File

@ -0,0 +1,24 @@
{
"schema": {
"https://buybutton.store/graphql": {
"headers": {
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJlYXQiOjE3NjcxMzkyMDAsInN1Yl90eXBlIjoyLCJ0b2tlbl90eXBlIjoxLCJjb3JzIjpbImh0dHBzOi8vZGV2ZWxvcGVyLmJpZ2NvbW1lcmNlLmNvbSJdLCJjaWQiOjEsImlhdCI6MTU3NjI1MzgyNCwic3ViIjoiM3dtZThrcWtrNjQwNzZueWljMGkzamk0NG5wajQ2byIsInNpZCI6OTk5MzMxNzg0LCJpc3MiOiJCQyJ9.Rqt6hNI2W-XSOzHl4pqtfhAOygwka6atCIaIZ_WAa9v3dOctnBlZpBV5wzd3ICCy4sTCOZ9mJwcFH5_CHmJpNQ"
}
}
},
"documents": [
{
"./lib/bigcommerce/api/queries/**/*.ts": {
"noRequire": true
}
}
],
"generates": {
"./lib/bigcommerce/schema.d.ts": {
"plugins": ["typescript", "typescript-operations"]
},
"./lib/bigcommerce/schema.graphql": {
"plugins": ["schema-ast"]
}
}
}

View File

@ -0,0 +1,52 @@
import {
CommerceAPI,
CommerceAPIOptions,
CommerceAPIFetchOptions,
} from 'lib/commerce/api';
import { GetAllProductsQuery } from '../schema';
import { getAllProductsQuery } from './operations/get-all-products';
type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>;
};
export default class BigcommerceAPI implements CommerceAPI {
commerceUrl: string;
apiToken: string;
constructor({ commerceUrl, apiToken }: CommerceAPIOptions) {
this.commerceUrl = commerceUrl;
this.apiToken = apiToken;
}
async fetch<T>(
query: string,
{ variables, preview }: CommerceAPIFetchOptions = {}
): Promise<T> {
const res = await fetch(this.commerceUrl + (preview ? '/preview' : ''), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.apiToken}`,
},
body: JSON.stringify({
query,
variables,
}),
});
const json = await res.json();
if (json.errors) {
console.error(json.errors);
throw new Error('Failed to fetch API');
}
return json.data;
}
async getAllProducts<T = GetAllProductsQuery>(
query: string = getAllProductsQuery
): Promise<T> {
const data = await this.fetch<RecursivePartial<GetAllProductsQuery>>(query);
return data as T;
}
}

View File

@ -0,0 +1,79 @@
export const responsiveImageFragment = /* GraphQL */ `
fragment responsiveImage on Image {
url320wide: url(width: 320)
url640wide: url(width: 640)
url960wide: url(width: 960)
url1280wide: url(width: 1280)
}
`;
export const getAllProductsQuery = /* GraphQL */ `
query getAllProducts {
site {
products(first: 4) {
pageInfo {
startCursor
endCursor
}
edges {
cursor
node {
entityId
name
path
brand {
name
}
description
prices {
price {
value
currencyCode
}
salePrice {
value
currencyCode
}
}
images {
edges {
node {
...responsiveImage
}
}
}
variants {
edges {
node {
entityId
defaultImage {
...responsiveImage
}
}
}
}
options {
edges {
node {
entityId
displayName
isRequired
values {
edges {
node {
entityId
label
}
}
}
}
}
}
}
}
}
}
}
${responsiveImageFragment}
`;

View File

@ -1,8 +1,9 @@
import {
CartProvider as CommerceCartProvider,
useCart as useCommerceCart,
} from '../commerce/cart';
import { Cart } from './index';
} from 'lib/commerce/cart';
export type Cart = any;
export function CartProvider({ children }) {
return <CommerceCartProvider>{children}</CommerceCartProvider>;

View File

@ -1,11 +1,8 @@
import {
CommerceProvider,
CommerceProvider as CoreCommerceProvider,
Connector,
HookResolver,
useCommerce as useComm,
} from '../commerce';
export type Cart = any;
useCommerce as useCoreCommerce,
} from 'lib/commerce';
async function getText(res: Response) {
try {
@ -23,11 +20,7 @@ async function getError(res: Response) {
return { message: await getText(res) };
}
async function fetcher(
url: string,
query: string,
resolver: HookResolver<Cart>
) {
async function fetcher(url: string, query: string) {
const res = await fetch(url);
if (res.ok) {
@ -37,42 +30,18 @@ async function fetcher(
throw await getError(res);
}
export const bigcommerce: Connector<Cart> = {
hooks: {
useCart: {
query: '',
resolver() {
return;
},
},
useAddItem: {
query: '',
resolver() {
return;
},
},
useUpdateItem: {
query: '',
resolver() {
return;
},
},
useRemoveItem: {
query: '',
resolver() {
return;
},
},
},
export const bigcommerce: Connector = {
locale: 'en-us',
fetcher,
};
// TODO: The connector should be extendable when a developer is using it
export function BigcommerceProvider({ children }) {
export function CommerceProvider({ children }) {
return (
<CommerceProvider connector={bigcommerce}>{children}</CommerceProvider>
<CoreCommerceProvider connector={bigcommerce}>
{children}
</CoreCommerceProvider>
);
}
export const useCommerce = () => useComm<Cart>();
export const useCommerce = () => useCoreCommerce();

1733
lib/bigcommerce/schema.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

24
lib/commerce/api/index.ts Normal file
View File

@ -0,0 +1,24 @@
export interface CommerceAPIOptions {
commerceUrl: string;
apiToken: string;
}
export interface CommerceAPIFetchOptions {
variables?: object;
preview?: boolean;
}
export interface CommerceAPI {
commerceUrl: string;
apiToken: string;
fetch<T>(query: string, queryData?: CommerceAPIFetchOptions): Promise<T>;
getAllProducts(query: string): Promise<any>;
}
// export default class CommerceAPI {
// getAllProducts(query: string) {
// }
// }

View File

@ -1,6 +1,8 @@
import { createContext, useContext } from 'react';
import useSWR, { responseInterface } from 'swr';
import { Cart, useCommerce } from '.';
import { useCommerce } from '.';
export type Cart = any;
export type CartResponse<C extends Cart> = responseInterface<C, Error> & {
isEmpty: boolean;

View File

@ -1,44 +1,20 @@
import { createContext, ReactNode, useContext } from 'react';
const Commerce = createContext<Connector<any>>(null);
const Commerce = createContext<Connector>(null);
export type Cart = any;
export type CommerceProps<C extends Cart> = {
export type CommerceProps = {
children?: ReactNode;
connector: Connector<C>;
connector: Connector;
};
export type Connector<C extends Cart> = {
hooks: {
useCart: Hook<C>;
useAddItem: Hook<C>;
useUpdateItem: Hook<C>;
useRemoveItem: Hook<C>;
};
export type Connector = {
fetcher: Fetcher<any>;
locale: string;
};
export type Hook<T extends any> = {
query?: string;
url?: string;
resolver: HookResolver<T>;
};
export type HookResolver<T> = (
fetcher: Fetcher<T>,
context: ResolverContext
) => T | Promise<T>;
export type Fetcher<T> = (...args: any) => T | Promise<T>;
export type ResolverContext = {
query?: string;
locale: string;
};
export function CommerceProvider({ children, connector }: CommerceProps<Cart>) {
export function CommerceProvider({ children, connector }: CommerceProps) {
if (!connector) {
throw new Error(
'CommerceProvider requires a valid headless commerce connector'
@ -48,6 +24,6 @@ export function CommerceProvider({ children, connector }: CommerceProps<Cart>) {
return <Commerce.Provider value={connector}>{children}</Commerce.Provider>;
}
export function useCommerce<C extends Cart>() {
return useContext(Commerce) as Connector<C>;
export function useCommerce<T extends Connector>() {
return useContext(Commerce) as T;
}

View File

@ -5,7 +5,12 @@
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
"start": "next start",
"generate": "graphql-codegen"
},
"graphql": {
"schema": "lib/bigcommerce/schema.graphql",
"documents": "lib/bigcommerce/**/*.{graphql,js,ts,jsx,tsx}"
},
"dependencies": {
"@tailwindcss/ui": "^0.6.2",
@ -18,15 +23,20 @@
"react-dom": "^16.13.1",
"swr": "^0.3.3"
},
"resolutions": {
"webpack": "^5.0.0-beta.30"
},
"devDependencies": {
"@graphql-codegen/cli": "^1.17.10",
"@graphql-codegen/schema-ast": "^1.17.8",
"@graphql-codegen/typescript": "^1.17.10",
"@graphql-codegen/typescript-operations": "^1.17.8",
"@types/node": "^14.11.2",
"@types/react": "^16.9.49",
"graphql": "^15.3.0",
"postcss-flexbugs-fixes": "^4.2.1",
"postcss-preset-env": "^6.7.0",
"tailwindcss": "^1.8.10",
"typescript": "^4.0.3"
},
"resolutions": {
"webpack": "^5.0.0-beta.30"
}
}

View File

@ -5,7 +5,7 @@
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,

2580
yarn.lock

File diff suppressed because it is too large Load Diff