_includes/queries.ts (117 lines of code) (raw):

import { Resource } from "../src/ResourceModels"; import { EleventyCollectionItem } from "../src/models"; import { POSSIBLE_RESOURCE_TYPES, RESOURCE_TYPES } from "../src/resourceType"; import { ResourceMapType } from "./config"; export type RESOURCE_MODELS_BY_TYPE< RESOURCE extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES = | RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES > = RESOURCE extends keyof ResourceMapType ? Array<ResourceMapType[RESOURCE]> : RESOURCE extends Array<RESOURCE_TYPES> ? // @ts-ignore Array<ResourceMapType[RESOURCE[number]]> : Resource[]; export type RESOURCE_MODEL_BY_TYPE< T extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES > = T extends keyof ResourceMapType ? ResourceMapType[T] : T extends Array<RESOURCE_TYPES> ? // @ts-ignore ResourceMapType[T[number]] : Resource; export type QueryFilter< T extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES = | RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES > = { channel?: string; limit?: number; resourceTypes?: T; tag?: string; customFilter?: (resource: RESOURCE_MODEL_BY_TYPE<T>) => boolean; sorter?: ( a: RESOURCE_MODEL_BY_TYPE<T>, b: RESOURCE_MODEL_BY_TYPE<T> ) => number; }; export function getResources< T extends RESOURCE_TYPES | POSSIBLE_RESOURCE_TYPES >( allResourcesList: Resource[], filter: QueryFilter<T> ): RESOURCE_MODELS_BY_TYPE<T> | null { let resources = allResourcesList; const types = filter && filter.resourceTypes != null ? Array.isArray(filter.resourceTypes) ? [...filter.resourceTypes] : [filter.resourceTypes] : undefined; if (types) { resources = resources.filter((r) => types.includes(r.resourceType!)); } const tag = filter && filter.tag; if (tag) { resources = resources.filter((r) => r.tags?.includes(tag)); } const channel = filter && filter.channel; if (channel) { resources = resources.filter((r) => r.channel == channel); } const customFilter = filter && filter.customFilter; if (customFilter) { resources = resources.filter((x) => customFilter(x as RESOURCE_MODEL_BY_TYPE<T>) ); } if (resources.length == 0) { return null; } const sorter = filter && filter.sorter; if (sorter) { // Sort by custom sorter resources.sort((a, b) => sorter(a as RESOURCE_MODEL_BY_TYPE<T>, b as RESOURCE_MODEL_BY_TYPE<T>) ); } else { // Sort in reverse date order resources.sort((a, b) => b.date.getTime() - a.date.getTime()); } const limit = filter && filter.limit; if (limit) { resources = resources.slice(0, limit); } return resources as RESOURCE_MODELS_BY_TYPE<T>; } // TODO PWE Get rid of this and just use collections.resourceMap export function getResource(resources: Resource[], url: string): Resource { return resources.filter((r) => r.url == url)[0]; } export function sortByFrontmatter( items: EleventyCollectionItem[], sortByOption?: string ) { if (!sortByOption) { return; } let sortOrder = 1; if (sortByOption[0] === "-") { sortOrder = -1; sortByOption = sortByOption.substring(1); } switch (sortByOption) { case "title": items.sort((a, b) => { const aTitle = a.data.title.toLowerCase(); const bTitle = b.data.title.toLowerCase(); return (aTitle > bTitle ? -1 : bTitle > aTitle ? 1 : 0) * sortOrder; }); break; case "date": items.sort((a, b) => { let result = a.page.date.getTime() - b.page.date.getTime(); return result * sortOrder; }); break; default: break; } }