Skip to content

Commit

Permalink
feat: automatically generate aggregation for page-type requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyklan committed Feb 9, 2024
1 parent 087dd49 commit 37a8e3c
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 100 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './makaira'
export { fetchMultiple } from './util/fetchMultiple'
36 changes: 18 additions & 18 deletions src/makaira/Makaira.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type NewRequestManagerOptions = {
makaira: Makaira
}

type RequestBuilderMapping = {
export type RequestBuilderMapping = {
snippet: SnippetRequestBuilder
page: PageRequestBuilder
search: SearchRequestBuilder
Expand All @@ -35,23 +35,23 @@ export abstract class Makaira {

public request<T extends FetchType>(type: T): RequestBuilderMapping[T] {
switch (type) {
case 'snippet':
return new SnippetRequestBuilder(this) as RequestBuilderMapping[T]
case 'document':
return new DocumentRequestBuilder(this) as RequestBuilderMapping[T]
case 'menu':
return new MenuRequestBuilder(this) as RequestBuilderMapping[T]
case 'privateSearch':
return new PageRequestBuilder(this) as RequestBuilderMapping[T]
case 'recommendation':
return new RecommendationRequestBuilder(
this
) as RequestBuilderMapping[T]
case 'search':
return new SearchRequestBuilder(this) as RequestBuilderMapping[T]
case 'page':
default:
return new PageRequestBuilder(this) as RequestBuilderMapping[T]
case 'snippet':
return new SnippetRequestBuilder(this) as RequestBuilderMapping[T]
case 'document':
return new DocumentRequestBuilder(this) as RequestBuilderMapping[T]
case 'menu':
return new MenuRequestBuilder(this) as RequestBuilderMapping[T]
case 'privateSearch':
return new PageRequestBuilder(this) as RequestBuilderMapping[T]
case 'recommendation':
return new RecommendationRequestBuilder(
this
) as RequestBuilderMapping[T]
case 'search':
return new SearchRequestBuilder(this) as RequestBuilderMapping[T]
case 'page':
default:
return new PageRequestBuilder(this) as RequestBuilderMapping[T]
}
}
}
4 changes: 2 additions & 2 deletions src/makaira/base/BaseRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type Constraints = {

export abstract class BaseRequest {
aggregations: {
[k: string]: number | string
[k: string]: any
}
public enableAggregations? = true
sorting: {
Expand Down Expand Up @@ -59,7 +59,7 @@ export abstract class BaseRequest {
this.aggregations = aggregations
}

public addAggregation(key: string, value: number | string) {
public addAggregation<T extends string>(key: T, value: any) {
this.aggregations[key] = value
}

Expand Down
15 changes: 15 additions & 0 deletions src/makaira/base/BaseRequestBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,23 @@ import type { Makaira } from '../Makaira'
import type { CustomFilter, RequestBodyCustomFilter } from './CustomFilter'
import { fetchFromMakaira } from './fetchFromMakaira'

export type ServerContext = {
req: {
headers: HeadersInit
}
params:
| {
[key: string]: string | string[] | undefined
}
| URLSearchParams
}

export class BaseRequestBuilder<T extends BaseRequest> {
protected request: T

protected serverContext?: ServerContext
protected params: ServerContext['params'] = new URLSearchParams()

protected seoUrl: string | undefined
protected apiInfo: Makaira

Expand Down Expand Up @@ -58,6 +72,7 @@ export class BaseRequestBuilder<T extends BaseRequest> {
return this.request
}

// TODO: add result typing
public fetch(additionalHeaders?: RequestInit['headers']) {
return fetchFromMakaira({
apiInfo: this.apiInfo,
Expand Down
88 changes: 88 additions & 0 deletions src/makaira/base/PageIshRequestBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Makaira } from '../Makaira'
import { BaseRequestBuilder } from './BaseRequestBuilder'
import { PageRequest } from './page/PageRequest'
import { SearchRequest } from './search'

// This is a shared request builder for the page and the search request builder
// they are both types of page requests
// nameing is hard
export class PageishRequestBuilder<
T extends PageRequest | SearchRequest
> extends BaseRequestBuilder<T> {
/**
*
*/
constructor(apiInfo: Makaira, builder: T) {
super(apiInfo, builder)
this.setCount(apiInfo.productsPerPage)
}

public setSorting(sorting: typeof PageRequest.prototype.sorting) {
this.request.sorting = sorting
return this
}

public setCount(count: number | string) {
this.request.count = parseInt(count as string, 10)
return this
}

public setOffset(offset: number | string) {
this.request.offset = parseInt(offset as string, 10)
return this
}

public generateAggregations(params: URLSearchParams) {
const filterObject: {
[key: string]: any
} = {}

for (const [key, value] of Array.from(params.entries())) {
if (!key.startsWith('filter[')) continue

// Remove 'filter[' from start and ']' from the end, then split by '][' to get individual keys
const path = key.slice(7, -1).split('][')
let current = filterObject

path.forEach((part: string | number, index: number) => {
const isLastPart: boolean = index === path.length - 1

if (isLastPart) {
if (Array.isArray(current[part])) {
// eslint-disable-next-line @typescript-eslint/no-extra-semi
;(current[part] as string[]).push(value)
return
}

if (current[part]) {
current[part] = [current[part], value]
return
}

current[part] = value
return
}

if (!current[part]) {
current[part] = isNaN(Number(path[index + 1])) ? {} : []
} else if (typeof current[part] === 'string') {
// Handle unexpected string value where an object or array is expected
current[part] = isNaN(Number(path[index + 1])) ? {} : [current[part]]
}

current = current[part]
})
}

this.request.aggregations = filterObject
return this
}

public generateOffset(params: URLSearchParams) {
const offset = params.get('offset')
if (offset) {
this.setOffset(offset)
}
return this
}
}
5 changes: 2 additions & 3 deletions src/makaira/base/page/PageRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@ import { BaseRequest } from '../BaseRequest'
import { FetchType } from '../../Makaira'

export class PageRequest extends BaseRequest {
protected searchPhrase: string = ''
protected searchPhrase = ''
protected isSearch = false

bundles?: { [key: string]: unknown }
slot?: unknown

url?: string

count: number
count!: number
offset: number
type: FetchType = 'page'

constructor() {
super()
this.count = 50
this.offset = 0
if (this.type === 'page') {
this.bundles = {}
Expand Down
72 changes: 4 additions & 68 deletions src/makaira/base/page/PageRequestBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import { PageRequest } from './PageRequest'
import type { Makaira } from '../../Makaira'
import { BaseRequestBuilder } from '../BaseRequestBuilder'
import { PageishRequestBuilder } from '../PageIshRequestBuilder'

// type BundleParams =
// | {
// bundleId?: undefined
// currentSlot?: never
// slots?: never
// }
// | {
// bundleId: string
// currentSlot: string
// slots: {
// [key: string]: string
// }
// }

export class PageRequestBuilder extends BaseRequestBuilder<PageRequest> {
export class PageRequestBuilder extends PageishRequestBuilder<PageRequest> {
constructor(apiInfo: Makaira) {
super(apiInfo, new PageRequest())
// this.setParams()
// this.setBundles()

if (this.seoUrl) {
this.setUrl(this.seoUrl)
}
Expand All @@ -34,55 +17,8 @@ export class PageRequestBuilder extends BaseRequestBuilder<PageRequest> {
return this
}

public setSorting(sorting: typeof PageRequest.prototype.sorting) {
this.request.sorting = sorting
return this
}

public setCount(count: number | string) {
this.request.count = parseInt(count as string, 10)
return this
}

public setOffset(offset: number | string) {
this.request.offset = parseInt(offset as string, 10)
public setBundles(bundles: PageRequest['bundles']) {
this.request.bundles = bundles
return this
}

// private setBundles() {
// const params = this.prepareBundleParams()
// const { bundleId, slots } = params
// if (!bundleId) {
// return
// }

// const bundles = {
// [bundleId]: {
// slots,
// },
// }

// this.request.bundles = bundles
// }

// private prepareBundleParams(): BundleParams {
// const cookies = parseCookies(this.ctx)
// const bundle = cookies['bundle']
// if (!bundle) {
// return {}
// }
// const bundleData = JSON.parse(bundle)
// const seoUrl = this.seoUrl!.replace(/\//g, '')

// const bundleId = this.params.get('bundleId')
// if (bundleId) {
// bundleData[seoUrl] = Object.fromEntries(this.params.entries())
// setCookie(this.ctx, 'bundle', JSON.stringify(bundleData), { path: '/' })
// return bundleData[seoUrl]
// } else if (bundleData[seoUrl]) {
// return bundleData[seoUrl]
// }

// return {}
// }
}
11 changes: 2 additions & 9 deletions src/makaira/base/search/SearchRequestBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Makaira } from '../../Makaira'
import { BaseRequestBuilder } from '../BaseRequestBuilder'
import { PageishRequestBuilder } from '../PageIshRequestBuilder'
import { SearchRequest } from './SearchRequest'

export class SearchRequestBuilder extends BaseRequestBuilder<SearchRequest> {
export class SearchRequestBuilder extends PageishRequestBuilder<SearchRequest> {
constructor(apiInfo: Makaira) {
super(apiInfo, new SearchRequest())
// this.setParams();
return this
}

// private setParams() {
// this.setSearchPhrase(this.params.get("searchPhrase") ?? "");
// this.setCount(this.params.get("count") ?? this.apiInfo.productsPerPage);
// this.setOffset(this.params.get("offset") ?? 0);
// }

public setUrl(url: string) {
this.request.url = encodeURI(url)
return this
Expand Down
7 changes: 7 additions & 0 deletions src/util/fetchMultiple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { BaseRequest, BaseRequestBuilder } from '../makaira'

export const fetchMultiple = (
...requests: BaseRequestBuilder<BaseRequest>[]
) => {
return Promise.all(requests.map((request) => request.fetch()))
}

0 comments on commit 37a8e3c

Please sign in to comment.