import { ServerRequest, ApiEntity, Size, SizeEntity, EntityId, EntityIdType, IdRequestType, RouteEntity, ApiRoute, } from "../types/index.js"; export function getRoutePath(...slugs: RouteEntity[]) { const path: string[] = [""]; for (const slug of slugs) { if (!slug) continue; if (typeof slug === "string") { path.push(slug); continue; } if (!slug.param) continue; let val = `:${slug.param}`; if (slug.optional) val = `${val}?`; path.push(val); } return path.join("/"); } export function getBaseUrl( ...prefix: ApiEntity[] ): ApiRoute { const routePath = getRoutePath(...prefix); function baseUrl(args: Request) { const { serverUrl } = args; return [serverUrl, ...prefix].join("/"); } baseUrl.Route = routePath; return baseUrl; } export function getBaseViewBoxUrl( ...prefix: ApiEntity[] ): ApiRoute { const baseUrl = getBaseUrl(...prefix); function baseViewBoxUrl(args: Request) { const { [SizeEntity.Width]: width, [SizeEntity.Height]: height } = args; return [baseUrl(args), width, height].join("/"); } baseViewBoxUrl.Route = getRoutePath( ...prefix, { param: SizeEntity.Width }, { param: SizeEntity.Height } ); return baseViewBoxUrl; } export function getIdUrl< RequiredId extends boolean, Entity extends keyof EntityIdType >( requiredId: RequiredId, entity: Entity, ...prefix: ApiEntity[] ): ApiRoute> { const baseUrl = getBaseUrl(...prefix, entity); const idKey = EntityId[entity]; function getIdUrl< Request extends IdRequestType >(args: Request) { const url = [baseUrl(args)]; const { [idKey]: id } = args; id && url.push(id); return url.join("/"); } getIdUrl.Route = getRoutePath(...prefix, entity, { param: idKey, optional: !requiredId, }); return getIdUrl; } export function getIdViewBoxUrl< RequiredId extends boolean, Entity extends keyof EntityIdType >( requiredId: RequiredId, entity: Entity, ...prefix: ApiEntity[] ): ApiRoute & Size> { const baseViewBoxUrl = getBaseViewBoxUrl(...prefix); const idKey = EntityId[entity]; function getIdViewBoxUrl< Request extends IdRequestType & Size >(args: Request) { const url = [baseViewBoxUrl(args), entity]; const { [idKey]: id } = args; id && url.push(id); return url.join("/"); } getIdViewBoxUrl.Route = getRoutePath( ...prefix, { param: SizeEntity.Width }, { param: SizeEntity.Height }, entity, { param: idKey, optional: !requiredId, } ); return getIdViewBoxUrl; } export class SearchBaseUrl { Items; Count; constructor(entity: Entity) { this.Items = getBaseUrl(ApiEntity.Search, entity); this.Count = getBaseUrl(ApiEntity.Search, ApiEntity.Count, entity); } } export class SearchFeatureUrl< RequiredId extends boolean, Entity extends keyof EntityIdType > extends SearchBaseUrl { Feature; constructor(requiredId: RequiredId, entity: Entity) { super(entity); this.Feature = { Items: getIdUrl(requiredId, entity, ApiEntity.Search, ApiEntity.Feature), Count: getIdUrl( requiredId, entity, ApiEntity.Search, ApiEntity.Count, ApiEntity.Feature ), }; } } export class SearchViewBoxUrl< RequiredId extends boolean, Entity extends keyof EntityIdType > extends SearchFeatureUrl { ViewBox; constructor(requiredId: RequiredId, entity: Entity) { super(requiredId, entity); this.ViewBox = { Items: getIdViewBoxUrl( requiredId, entity, ApiEntity.Search, ApiEntity.Feature ), Count: getIdViewBoxUrl( requiredId, entity, ApiEntity.Search, ApiEntity.Count, ApiEntity.Feature ), }; } }