forked from crowetic/commerce
Use functions instead of a class
This commit is contained in:
parent
e242525476
commit
2971b4f802
@ -1,20 +1,6 @@
|
|||||||
import {
|
import { CommerceAPIConfig } from 'lib/commerce/api';
|
||||||
CommerceAPI,
|
import { GetAllProductsQueryVariables } from '../schema';
|
||||||
CommerceAPIOptions,
|
import fetchAPI from './utils/fetch-api';
|
||||||
CommerceAPIFetchOptions,
|
|
||||||
} from 'lib/commerce/api';
|
|
||||||
import { GetAllProductsQuery, GetAllProductsQueryVariables } from '../schema';
|
|
||||||
import { getAllProductsQuery } from './operations/get-all-products';
|
|
||||||
|
|
||||||
type RecursivePartial<T> = {
|
|
||||||
[P in keyof T]?: RecursivePartial<T[P]>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface GetAllProductsResult<T> {
|
|
||||||
products: T extends GetAllProductsQuery
|
|
||||||
? T['site']['products']['edges']
|
|
||||||
: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Images {
|
export interface Images {
|
||||||
small?: ImageOptions;
|
small?: ImageOptions;
|
||||||
@ -28,10 +14,6 @@ export interface ImageOptions {
|
|||||||
height?: number;
|
height?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BigcommerceAPIOptions extends CommerceAPIOptions {
|
|
||||||
images?: Images;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ProductImageVariables = Pick<
|
export type ProductImageVariables = Pick<
|
||||||
GetAllProductsQueryVariables,
|
GetAllProductsQueryVariables,
|
||||||
| 'imgSmallWidth'
|
| 'imgSmallWidth'
|
||||||
@ -44,83 +26,51 @@ export type ProductImageVariables = Pick<
|
|||||||
| 'imgXLHeight'
|
| 'imgXLHeight'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type ProductVariables = Images &
|
export interface BigcommerceConfig extends CommerceAPIConfig {
|
||||||
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>;
|
images?: Images;
|
||||||
|
readonly imageVariables?: ProductImageVariables;
|
||||||
export default class BigcommerceAPI implements CommerceAPI {
|
}
|
||||||
commerceUrl: string;
|
|
||||||
apiToken: string;
|
const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL;
|
||||||
imageVariables?: ProductImageVariables;
|
const API_TOKEN = process.env.BIGCOMMERCE_STOREFRONT_API_TOKEN;
|
||||||
|
|
||||||
constructor({ commerceUrl, apiToken, images }: BigcommerceAPIOptions) {
|
if (!API_URL) {
|
||||||
this.commerceUrl = commerceUrl;
|
throw new Error(
|
||||||
this.apiToken = apiToken;
|
`The environment variable BIGCOMMERCE_STOREFRONT_API_URL is missing and it's required to access your store`
|
||||||
this.imageVariables = {
|
);
|
||||||
imgSmallWidth: images?.small?.width,
|
}
|
||||||
imgSmallHeight: images?.small?.height,
|
|
||||||
imgMediumWidth: images?.medium?.height,
|
if (!API_TOKEN) {
|
||||||
imgMediumHeight: images?.medium?.height,
|
throw new Error(
|
||||||
imgLargeWidth: images?.large?.height,
|
`The environment variable BIGCOMMERCE_STOREFRONT_API_TOKEN is missing and it's required to access your store`
|
||||||
imgLargeHeight: images?.large?.height,
|
);
|
||||||
imgXLWidth: images?.xl?.height,
|
}
|
||||||
imgXLHeight: images?.xl?.height,
|
|
||||||
};
|
const config: BigcommerceConfig = {
|
||||||
}
|
commerceUrl: API_URL,
|
||||||
|
apiToken: API_TOKEN,
|
||||||
async fetch<Q, V = any>(
|
fetch: fetchAPI,
|
||||||
query: string,
|
get imageVariables() {
|
||||||
{ variables, preview }: CommerceAPIFetchOptions<V> = {}
|
const { images } = this;
|
||||||
): Promise<Q> {
|
return images
|
||||||
const res = await fetch(this.commerceUrl + (preview ? '/preview' : ''), {
|
? {
|
||||||
method: 'POST',
|
imgSmallWidth: images.small?.width,
|
||||||
headers: {
|
imgSmallHeight: images.small?.height,
|
||||||
'Content-Type': 'application/json',
|
imgMediumWidth: images.medium?.height,
|
||||||
Authorization: `Bearer ${this.apiToken}`,
|
imgMediumHeight: images.medium?.height,
|
||||||
},
|
imgLargeWidth: images.large?.height,
|
||||||
body: JSON.stringify({
|
imgLargeHeight: images.large?.height,
|
||||||
query,
|
imgXLWidth: images.xl?.height,
|
||||||
variables,
|
imgXLHeight: images.xl?.height,
|
||||||
}),
|
}
|
||||||
});
|
: undefined;
|
||||||
|
},
|
||||||
const json = await res.json();
|
};
|
||||||
if (json.errors) {
|
|
||||||
console.error(json.errors);
|
export function getConfig() {
|
||||||
throw new Error('Failed to fetch API');
|
return config;
|
||||||
}
|
}
|
||||||
return json.data;
|
|
||||||
}
|
export function setConfig(newConfig: Partial<BigcommerceConfig>) {
|
||||||
|
Object.assign(config, newConfig);
|
||||||
async getAllProducts<T, V = any>(opts: {
|
|
||||||
query: string;
|
|
||||||
variables?: V;
|
|
||||||
}): Promise<GetAllProductsResult<T>>;
|
|
||||||
|
|
||||||
async getAllProducts(opts?: {
|
|
||||||
query?: string;
|
|
||||||
variables?: ProductVariables;
|
|
||||||
}): Promise<GetAllProductsResult<GetAllProductsQuery>>;
|
|
||||||
|
|
||||||
async getAllProducts({
|
|
||||||
query = getAllProductsQuery,
|
|
||||||
variables: vars,
|
|
||||||
}: {
|
|
||||||
query?: string;
|
|
||||||
variables?: ProductVariables;
|
|
||||||
} = {}): Promise<
|
|
||||||
GetAllProductsResult<RecursivePartial<GetAllProductsQuery>>
|
|
||||||
> {
|
|
||||||
const variables: GetAllProductsQueryVariables = {
|
|
||||||
...this.imageVariables,
|
|
||||||
...vars,
|
|
||||||
};
|
|
||||||
const data = await this.fetch<RecursivePartial<GetAllProductsQuery>>(
|
|
||||||
query,
|
|
||||||
{ variables }
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
products: data?.site?.products?.edges,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
import {
|
||||||
|
GetAllProductsQuery,
|
||||||
|
GetAllProductsQueryVariables,
|
||||||
|
} from 'lib/bigcommerce/schema';
|
||||||
|
import { getConfig, Images, ProductImageVariables } from '..';
|
||||||
|
import { RecursivePartial } from '../types';
|
||||||
|
|
||||||
export const getAllProductsQuery = /* GraphQL */ `
|
export const getAllProductsQuery = /* GraphQL */ `
|
||||||
query getAllProducts(
|
query getAllProducts(
|
||||||
$first: Int = 10
|
$first: Int = 10
|
||||||
@ -94,3 +101,46 @@ export const getAllProductsQuery = /* GraphQL */ `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export interface GetAllProductsResult<T> {
|
||||||
|
products: T extends GetAllProductsQuery
|
||||||
|
? T['site']['products']['edges']
|
||||||
|
: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ProductVariables = Images &
|
||||||
|
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>;
|
||||||
|
|
||||||
|
async function getAllProducts<T, V = any>(opts: {
|
||||||
|
query: string;
|
||||||
|
variables?: V;
|
||||||
|
}): Promise<GetAllProductsResult<T>>;
|
||||||
|
|
||||||
|
async function getAllProducts(opts?: {
|
||||||
|
query?: string;
|
||||||
|
variables?: ProductVariables;
|
||||||
|
}): Promise<GetAllProductsResult<GetAllProductsQuery>>;
|
||||||
|
|
||||||
|
async function getAllProducts({
|
||||||
|
query = getAllProductsQuery,
|
||||||
|
variables: vars,
|
||||||
|
}: {
|
||||||
|
query?: string;
|
||||||
|
variables?: ProductVariables;
|
||||||
|
} = {}): Promise<GetAllProductsResult<RecursivePartial<GetAllProductsQuery>>> {
|
||||||
|
const config = getConfig();
|
||||||
|
const variables: GetAllProductsQueryVariables = {
|
||||||
|
...config.imageVariables,
|
||||||
|
...vars,
|
||||||
|
};
|
||||||
|
const data = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
|
||||||
|
query,
|
||||||
|
{ variables }
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
products: data?.site?.products?.edges,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getAllProducts;
|
||||||
|
3
lib/bigcommerce/api/types/index.ts
Normal file
3
lib/bigcommerce/api/types/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export type RecursivePartial<T> = {
|
||||||
|
[P in keyof T]?: RecursivePartial<T[P]>;
|
||||||
|
};
|
27
lib/bigcommerce/api/utils/fetch-api.ts
Normal file
27
lib/bigcommerce/api/utils/fetch-api.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { CommerceAPIFetchOptions } from 'lib/commerce/api';
|
||||||
|
import { getConfig } from '..';
|
||||||
|
|
||||||
|
export default async function fetchAPI<Q, V = any>(
|
||||||
|
query: string,
|
||||||
|
{ variables, preview }: CommerceAPIFetchOptions<V> = {}
|
||||||
|
): Promise<Q> {
|
||||||
|
const config = getConfig();
|
||||||
|
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${config.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;
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
import BigcommerceAPI from './bigcommerce/api';
|
|
||||||
|
|
||||||
const API_URL = process.env.NEXT_EXAMPLE_BIGCOMMERCE_STOREFRONT_API_URL!;
|
|
||||||
const API_TOKEN = process.env.NEXT_EXAMPLE_BIGCOMMERCE_STOREFRONT_API_TOKEN!;
|
|
||||||
|
|
||||||
export const commerce = new BigcommerceAPI({
|
|
||||||
commerceUrl: API_URL,
|
|
||||||
apiToken: API_TOKEN,
|
|
||||||
});
|
|
@ -1,6 +1,10 @@
|
|||||||
export interface CommerceAPIOptions {
|
export interface CommerceAPIConfig {
|
||||||
commerceUrl: string;
|
commerceUrl: string;
|
||||||
apiToken: string;
|
apiToken: string;
|
||||||
|
fetch<Q, V = any>(
|
||||||
|
query: string,
|
||||||
|
queryData?: CommerceAPIFetchOptions<V>
|
||||||
|
): Promise<Q>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommerceAPIFetchOptions<V> {
|
export interface CommerceAPIFetchOptions<V> {
|
||||||
@ -8,14 +12,8 @@ export interface CommerceAPIFetchOptions<V> {
|
|||||||
preview?: boolean;
|
preview?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommerceAPI {
|
// TODO: define interfaces for all the available operations
|
||||||
commerceUrl: string;
|
|
||||||
apiToken: string;
|
|
||||||
|
|
||||||
fetch<Q, V = any>(
|
// export interface CommerceAPI {
|
||||||
query: string,
|
// getAllProducts(options?: { query: string }): Promise<any>;
|
||||||
queryData?: CommerceAPIFetchOptions<V>
|
// }
|
||||||
): Promise<Q>;
|
|
||||||
|
|
||||||
getAllProducts(options?: { query: string }): Promise<any>;
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
|
import { GetStaticPropsContext, InferGetStaticPropsType } from 'next';
|
||||||
import { commerce } from 'lib/commerce-api';
|
import getAllProducts from 'lib/bigcommerce/api/operations/get-all-products';
|
||||||
import { Layout } from '@components/core';
|
import { Layout } from '@components/core';
|
||||||
|
|
||||||
export async function getStaticProps({ preview }: GetStaticPropsContext) {
|
export async function getStaticProps({ preview }: GetStaticPropsContext) {
|
||||||
const { products } = await commerce.getAllProducts();
|
const { products } = await getAllProducts();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { products },
|
props: { products },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user