Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 36x 36x 36x 13x 10x 6x 10x 10x 21x 12x 21x 12x 7x 12x 21x 12x 12x 12x 12x 11x 11x 11x | // Taxonomy Route Helpers
import { eq, asc, and } from "drizzle-orm";
import type { DrizzleD1Database } from "drizzle-orm/d1";
import type { SQLiteTableWithColumns } from "drizzle-orm/sqlite-core";
import { createDualCache, CACHE_TTL } from "../../lib/cache";
/**
* Query active taxonomy items from a table
* Standard pattern: isActive = true, ordered by sortOrder
*/
export async function queryActiveTaxonomy<T>(
// biome-ignore lint/suspicious/noExplicitAny: Accept both schema-typed and untyped DrizzleD1Database
db: DrizzleD1Database<any>,
// biome-ignore lint/suspicious/noExplicitAny: Drizzle ORM generic table type requires any for dynamic column access
table: SQLiteTableWithColumns<any>,
whereClause?: ReturnType<typeof eq>,
): Promise<T[]> {
const baseCondition = eq(
table.isActive as unknown as Parameters<typeof eq>[0],
true,
);
const condition = whereClause
? and(baseCondition, whereClause)
: baseCondition;
return db
.select()
.from(table)
.where(condition)
.orderBy(
asc(table.sortOrder as unknown as Parameters<typeof asc>[0]),
) as Promise<T[]>;
}
/**
* Group items by a category field
*/
export function groupByCategory<T extends { category: string }>(
items: T[],
): Record<string, T[]> {
return items.reduce(
(acc: Record<string, T[]>, item) => {
if (!acc[item.category]) {
acc[item.category] = [];
}
acc[item.category].push(item);
return acc;
},
{} as Record<string, T[]>,
);
}
/**
* Build hierarchical structure for parent/child items
*/
export function buildHierarchy<
T extends { id: string; parentId: string | null },
>(items: T[]): (T & { children: T[] })[] {
const rootItems = items.filter((item) => !item.parentId);
const childMap = items.reduce(
(acc: Record<string, T[]>, item) => {
if (item.parentId) {
if (!acc[item.parentId]) {
acc[item.parentId] = [];
}
acc[item.parentId].push(item);
}
return acc;
},
{} as Record<string, T[]>,
);
return rootItems.map((parent) => ({
...parent,
children: childMap[parent.id] || [],
}));
}
/**
* Dual-layer cached taxonomy fetch (L1 in-memory + L2 KV)
*/
export async function cachedTaxonomyQuery<T>(
c: { env: CloudflareBindings; executionCtx: ExecutionContext },
cacheKey: string,
fetcher: () => Promise<T>,
): Promise<T> {
const dualCache = createDualCache(c.env.KV_CACHE);
const cached = await dualCache.get<T>(cacheKey);
if (cached) return cached;
const data = await fetcher();
c.executionCtx.waitUntil(
dualCache.put(cacheKey, data, {
l1Ttl: CACHE_TTL.TAXONOMY_L1,
l2Ttl: CACHE_TTL.TAXONOMY_L2,
}),
);
return data;
}
|