Skip to content

Instantly share code, notes, and snippets.

@jayo78
Last active June 23, 2024 22:59
Show Gist options
  • Save jayo78/512c5068c1b0bec61414e68be32a1335 to your computer and use it in GitHub Desktop.
Save jayo78/512c5068c1b0bec61414e68be32a1335 to your computer and use it in GitHub Desktop.
import { FragileApiProduct, FragileApiProductCollection } from 'types';
import fetch from 'node-fetch';
export class FragileApi {
private static instance: FragileApi;
private readonly apiUrl: string;
private readonly tenantId: string;
private readonly authToken?: string;
constructor(apiUrl: string, tenantId: string, authToken?: string) {
if (!apiUrl || !tenantId) {
throw new Error(
`Fragile: Cannot instantiate Fragile API without URL or Tenant ID`
);
}
this.apiUrl = apiUrl;
this.tenantId = tenantId;
this.authToken = authToken;
}
public static getInstance(): FragileApi {
if (FragileApi.instance) {
return FragileApi.instance;
}
const { FRAGILE_API_URL, FRAGILE_TENANT_ID, FRAGILE_AUTH_TOKEN } =
process.env;
try {
const instance = new FragileApi(
FRAGILE_API_URL,
FRAGILE_TENANT_ID,
FRAGILE_AUTH_TOKEN
);
FragileApi.instance = instance;
return instance;
} catch (ex) {
throw new Error(
`Fragile: Missing environment variables FRAGILE_API_URL and/or FRAGILE_TENANT_ID`
);
}
}
public async getProducts(): Promise<{ data: FragileApiProduct[] }> {
const res = await fetch(
`${this.apiUrl}/products?expand=skus,price,upgrades`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-fragile-tenant': this.tenantId,
...(this.authToken
? { Authorization: `Bearer ${this.authToken}` }
: {}),
},
}
);
if (!res.ok) {
throw new Error('Fragile: Unable to fetch products from Fragile API');
}
const resp = await res.json();
return resp;
}
public async getProduct(
productId: string
): Promise<{ data: FragileApiProduct }> {
const res = await fetch(
`${this.apiUrl}/products/${productId}?expand=skus,price,upgrades`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-fragile-tenant': this.tenantId,
...(this.authToken
? { Authorization: `Bearer ${this.authToken}` }
: {}),
},
}
);
if (!res.ok) {
throw new Error('Fragile: Unable to fetch products from Fragile API');
}
const resp = await res.json();
return resp;
}
public async getProductCollection(
productCollectionId: string
): Promise<FragileApiProductCollection> {
const res = await fetch(
`${this.apiUrl}/product-collections/${productCollectionId}?expand=products`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-fragile-tenant': this.tenantId,
...(this.authToken
? { Authorization: `Bearer ${this.authToken}` }
: {}),
},
}
);
if (!res.ok) {
throw new Error('Fragile: Unable to fetch products from Fragile API');
}
const resp = await res.json();
const productCollection: FragileApiProductCollection = resp.data;
productCollection.products = (
await Promise.all(
productCollection.products.map(p => this.getProduct(p.productId))
)
).map(p => p.data);
return productCollection;
}
public getCollectionMonthlyPrice(productCollection: FragileApiProductCollection) {
return productCollection.products.reduce(
(acc, product) =>
acc +
(product.price?.recurringInterval === 'MONTH'
? product.price?.amount ?? 0
: 0),
0
),
}
}
/*
* FRAGILE TYPES
*/
export type FragileEntityBaseFields = {
tenantId: string;
id: string;
metadata: any;
};
export type FragileApiPrice = FragileEntityBaseFields & {
isActive: boolean;
type: 'RECURRING' | 'ONE_TIME';
recurringInterval: 'MONTH' | 'WEEK' | 'HOUR' | undefined;
recurringIntervalCount: number;
amount: number;
};
export type FragileApiSku = FragileEntityBaseFields & {
name: string;
displayName: string;
type: 'DEVICE' | 'FEE' | 'MERCHANDISE' | 'PART' | 'SERVICE';
};
export type FragileApiUpgradeOption = FragileEntityBaseFields & {
name: string;
displayName: string;
displayOrder: number;
skus: FragileApiSku[];
priceId: string | null;
price: FragileApiPrice | null;
isActive: boolean;
};
export type FragileApiUpgrade = FragileEntityBaseFields & {
name: string;
displayName: string;
description: string;
displayOrder: number;
productId: string;
options: FragileApiUpgradeOption[];
};
export type FragileApiProduct = FragileEntityBaseFields & {
productId: string;
name: string;
displayName: string;
isTransactional: boolean;
requireScreening: boolean;
priceId: string;
price: FragileApiPrice;
skus: FragileApiSku[];
upgrades: FragileApiUpgrade[];
};
export type FragileApiProductCollection = FragileEntityBaseFields & {
name: string;
displayName: string;
products: FragileApiProduct[];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment