Add fococoffee endpoints
This commit is contained in:
@@ -23,6 +23,7 @@ import { RedirectsModule } from './redirects/redirects.module';
|
||||
import { FileModule } from './file/file.module';
|
||||
import { FocoLiveModule } from './foco-live/foco-live.module';
|
||||
import { PowModule } from './pow/pow.module';
|
||||
import { FocoCoffeeModule } from './fococoffee/fococoffee.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -80,6 +81,7 @@ import { PowModule } from './pow/pow.module';
|
||||
FileModule,
|
||||
FocoLiveModule,
|
||||
PowModule,
|
||||
FocoCoffeeModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
|
16
src/fococoffee/bindle.service.ts
Normal file
16
src/fococoffee/bindle.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ShopifyProduct, parseShopifyProduct } from './shopifyUtils';
|
||||
import axios from 'axios';
|
||||
|
||||
@Injectable()
|
||||
export class BindleService {
|
||||
public readonly shopifyUrl = 'https://bindlecoffee.com/products.json'
|
||||
|
||||
public async fetchProducts(): Promise<ShopifyProduct<Date>[]> {
|
||||
const response = await axios.get(this.shopifyUrl)
|
||||
if (response.status !== 200) {
|
||||
throw new Error('Failed to fetch products')
|
||||
}
|
||||
return response.data.products.map(parseShopifyProduct);
|
||||
}
|
||||
}
|
48
src/fococoffee/fococoffee.controller.ts
Normal file
48
src/fococoffee/fococoffee.controller.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { HarbingerService } from './harbinger.service';
|
||||
import { FocoCoffeeService } from './fococoffee.service';
|
||||
import { LimaService } from './lima.service';
|
||||
import { BindleService } from './bindle.service';
|
||||
import { ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@Controller('fococoffee')
|
||||
@ApiTags('fococoffee')
|
||||
export class FocoCoffeeController {
|
||||
|
||||
constructor(
|
||||
private readonly focoCoffeeService: FocoCoffeeService,
|
||||
private readonly harbingerService: HarbingerService,
|
||||
private readonly limaService: LimaService,
|
||||
private readonly bindleService: BindleService
|
||||
) { }
|
||||
|
||||
@Get('harbinger/products')
|
||||
@ApiResponse({ status: 200, description: 'Returns the list of Harbinger products' })
|
||||
async getHarbingerProducts() {
|
||||
return this.harbingerService.fetchProducts()
|
||||
}
|
||||
|
||||
@Get('lima/products')
|
||||
@ApiResponse({ status: 200, description: 'Returns the list of Lima products' })
|
||||
async getLimaProducts() {
|
||||
return this.limaService.fetchProducts()
|
||||
}
|
||||
|
||||
@Get('bindle/products')
|
||||
@ApiResponse({ status: 200, description: 'Returns the list of Bindle products' })
|
||||
async getBindleProducts() {
|
||||
return this.bindleService.fetchProducts()
|
||||
}
|
||||
|
||||
@Get('beans')
|
||||
@ApiResponse({ status: 200, description: 'Returns the list of coffee bean products from all suppliers' })
|
||||
async getBeans() {
|
||||
return this.focoCoffeeService.getBeans()
|
||||
}
|
||||
|
||||
@Get('products')
|
||||
@ApiResponse({ status: 200, description: 'Returns the list of all products from all suppliers' })
|
||||
async getAllProducts() {
|
||||
return this.focoCoffeeService.getAllProducts()
|
||||
}
|
||||
}
|
13
src/fococoffee/fococoffee.module.ts
Normal file
13
src/fococoffee/fococoffee.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { FocoCoffeeController } from './fococoffee.controller';
|
||||
import { FocoCoffeeService } from './fococoffee.service';
|
||||
import { HarbingerService } from './harbinger.service';
|
||||
import { LimaService } from './lima.service';
|
||||
import { BindleService } from './bindle.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [FocoCoffeeController],
|
||||
providers: [FocoCoffeeService, HarbingerService, LimaService, BindleService]
|
||||
})
|
||||
export class FocoCoffeeModule { }
|
39
src/fococoffee/fococoffee.service.ts
Normal file
39
src/fococoffee/fococoffee.service.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { LimaService } from './lima.service';
|
||||
import { HarbingerService } from './harbinger.service';
|
||||
import { BindleService } from './bindle.service';
|
||||
|
||||
@Injectable()
|
||||
export class FocoCoffeeService {
|
||||
constructor(
|
||||
private readonly limaService: LimaService,
|
||||
private readonly harbingerService: HarbingerService,
|
||||
private readonly bindleService: BindleService
|
||||
) { }
|
||||
|
||||
public async getAllProducts() {
|
||||
const limaProducts = await this.limaService.fetchProducts()
|
||||
const harbingerProducts = await this.harbingerService.fetchProducts()
|
||||
const bindleProducts = await this.bindleService.fetchProducts()
|
||||
return {
|
||||
lima: limaProducts,
|
||||
harbinger: harbingerProducts,
|
||||
bindle: bindleProducts
|
||||
}
|
||||
}
|
||||
|
||||
public async getBeans() {
|
||||
const limaBeans = await this.limaService.fetchProducts()
|
||||
const harbingerBeans = await this.harbingerService.fetchProducts()
|
||||
const bindleBeans = await this.bindleService.fetchProducts()
|
||||
return {
|
||||
lima: limaBeans
|
||||
.filter(p => p.tags.includes("Coffee"))
|
||||
.filter(p => !p.title.toLocaleLowerCase().includes("subscription"))
|
||||
.filter(p => p.handle !== "lima-sample-pack")
|
||||
,
|
||||
harbinger: harbingerBeans.filter(p => p.product_type === "Packaged Coffee"),
|
||||
bindle: bindleBeans.filter(p => p.product_type === "Coffee, Roasted")
|
||||
}
|
||||
}
|
||||
}
|
16
src/fococoffee/harbinger.service.ts
Normal file
16
src/fococoffee/harbinger.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ShopifyProduct, parseShopifyProduct } from './shopifyUtils';
|
||||
import axios from 'axios';
|
||||
|
||||
@Injectable()
|
||||
export class HarbingerService {
|
||||
public readonly shopifyUrl = 'https://harbingercoffee.com/products.json'
|
||||
|
||||
public async fetchProducts(): Promise<ShopifyProduct<Date>[]> {
|
||||
const response = await axios.get(this.shopifyUrl)
|
||||
if (response.status !== 200) {
|
||||
throw new Error('Failed to fetch products')
|
||||
}
|
||||
return response.data.products.map(parseShopifyProduct);
|
||||
}
|
||||
}
|
16
src/fococoffee/lima.service.ts
Normal file
16
src/fococoffee/lima.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ShopifyProduct, parseShopifyProduct } from './shopifyUtils';
|
||||
import axios from 'axios';
|
||||
|
||||
@Injectable()
|
||||
export class LimaService {
|
||||
public readonly shopifyUrl = 'https://www.limacoffeeroasters.com/products.json'
|
||||
|
||||
public async fetchProducts(): Promise<ShopifyProduct<Date>[]> {
|
||||
const response = await axios.get(this.shopifyUrl)
|
||||
if (response.status !== 200) {
|
||||
throw new Error('Failed to fetch products')
|
||||
}
|
||||
return response.data.products.map(parseShopifyProduct);
|
||||
}
|
||||
}
|
74
src/fococoffee/shopifyUtils.ts
Normal file
74
src/fococoffee/shopifyUtils.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { pipe } from "ramda";
|
||||
|
||||
export interface ShopifyVariant<T> {
|
||||
id: number;
|
||||
title: string;
|
||||
price: string;
|
||||
sku: string;
|
||||
position: number;
|
||||
option1?: string;
|
||||
option2?: string;
|
||||
option3?: string;
|
||||
taxable: boolean;
|
||||
grams: number;
|
||||
available: boolean;
|
||||
created_at: T;
|
||||
updated_at: T;
|
||||
}
|
||||
|
||||
export interface ShopifyImage<T> {
|
||||
id: number;
|
||||
created_at: T;
|
||||
position: number;
|
||||
updated_at: T;
|
||||
product_id: number;
|
||||
variant_ids: number[];
|
||||
src: string;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface ShopifyOption {
|
||||
name: string;
|
||||
position: number;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
export interface ShopifyProduct<T> {
|
||||
id: number;
|
||||
title: string;
|
||||
handle: string;
|
||||
body_html: string;
|
||||
published_at: T;
|
||||
created_at: T;
|
||||
vendor: string;
|
||||
product_type: string;
|
||||
updated_at: T;
|
||||
tags: string[];
|
||||
variants: ShopifyVariant<T>[];
|
||||
images: ShopifyImage<T>[];
|
||||
options: ShopifyOption[];
|
||||
}
|
||||
|
||||
|
||||
export const parseShopifyProductDates = (productIn: ShopifyProduct<string | Date>): ShopifyProduct<Date> => {
|
||||
return {
|
||||
...productIn,
|
||||
published_at: new Date(productIn.published_at),
|
||||
created_at: new Date(productIn.created_at),
|
||||
updated_at: new Date(productIn.updated_at),
|
||||
variants: productIn.variants.map((variant) => ({
|
||||
...variant,
|
||||
created_at: new Date(variant.created_at),
|
||||
updated_at: new Date(variant.updated_at),
|
||||
})),
|
||||
images: productIn.images.map((image) => ({
|
||||
...image,
|
||||
created_at: new Date(image.created_at),
|
||||
updated_at: new Date(image.updated_at),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export const parseShopifyProduct = pipe(parseShopifyProductDates);
|
Reference in New Issue
Block a user