Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cf-proxy/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface ComponentCatalogQueryParams {
search?: string
is_basic?: string
is_preferred?: string
is_extended_promotional?: string
}

export async function queryComponentCatalog(
Expand All @@ -22,6 +23,7 @@ export async function queryComponentCatalog(
package: string | null
basic: number | null
preferred: number | null
is_extended_promotional: number | null
description: string | null
stock: number | null
price: string | null
Expand All @@ -34,6 +36,7 @@ export async function queryComponentCatalog(
subcategory_name: params.subcategory_name,
is_basic: params.is_basic,
is_preferred: params.is_preferred,
is_extended_promotional: params.is_extended_promotional,
limit: "100",
})

Expand Down
4 changes: 3 additions & 1 deletion cf-proxy/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CacheService, addCorsHeaders, addVaryHeader } from "./cache-service"
import { queryComponentCatalog } from "./components"
import { getD1Client } from "./db/get-d1-client"
import { getD1Handler } from "./d1-routes"
import { getD1Client } from "./db/get-d1-client"
import { renderD1TablePage, renderHomePage } from "./render"
import { searchIndex } from "./search"

Expand Down Expand Up @@ -367,6 +367,7 @@ async function handleD1Search(
package: row.package ?? "",
is_basic: Boolean(row.basic),
is_preferred: Boolean(row.preferred),
is_extended_promotional: Boolean(row.is_extended_promotional),
description: row.description ?? "",
stock: row.stock ?? 0,
price: row.price1 ?? extractSmallQuantityPrice(row.price),
Expand Down Expand Up @@ -491,6 +492,7 @@ async function handleD1ComponentsList(
subcategory: row.subcategory ?? "",
is_basic: Boolean(row.basic),
is_preferred: Boolean(row.preferred),
is_extended_promotional: Boolean(row.is_extended_promotional),
})),
}

Expand Down
8 changes: 6 additions & 2 deletions cf-proxy/src/render.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
type FilterOptions,
type QueryParams,
ROUTE_TO_TABLE,
TABLE_CONFIGS,
TABLE_RESPONSE_KEY,
type QueryParams,
type FilterOptions,
} from "./handlers"

const escapeHtml = (value: unknown): string =>
Expand Down Expand Up @@ -147,6 +147,7 @@ const COLUMN_LABELS: Record<string, string> = {
in_stock: "In Stock",
is_basic: "Basic",
is_preferred: "Preferred",
is_extended_promotional: "Extended Promotional",
capacitance_farads: "Capacitance",
tolerance_fraction: "Tolerance",
voltage_rating: "Voltage",
Expand Down Expand Up @@ -546,6 +547,9 @@ const renderComponentsFilters = (
<div>
<label>Preferred Part:<input type="checkbox" name="is_preferred" value="true"${params.is_preferred === "true" ? " checked" : ""} /></label>
</div>
<div>
<label>Extended Promotional:<input type="checkbox" name="is_extended_promotional" value="true"${params.is_extended_promotional === "true" ? " checked" : ""} /></label>
</div>
<button type="submit">Filter</button>
</form>`

Expand Down
12 changes: 11 additions & 1 deletion cf-proxy/src/search.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sql, type Kysely, type RawBuilder } from "kysely"
import { type Kysely, type RawBuilder, sql } from "kysely"
import type { DB } from "./db/types"
import { buildSearchTokenGroups } from "./search-query"

Expand All @@ -9,6 +9,7 @@ export interface SearchQueryParams {
limit?: string
is_basic?: string
is_preferred?: string
is_extended_promotional?: string
}

interface SearchRow {
Expand All @@ -21,6 +22,7 @@ interface SearchRow {
price1: number | null
basic: number | null
preferred: number | null
is_extended_promotional: number | null
category: string | null
subcategory: string | null
}
Expand Down Expand Up @@ -109,6 +111,13 @@ export async function searchIndex(
if (params.is_preferred === "true" || params.is_preferred === "1") {
conditions.push(sql`search_index.preferred = 1`)
}
if (
params.is_extended_promotional === "true" ||
params.is_extended_promotional === "1"
) {
conditions.push(sql`search_index.preferred = 1`)
conditions.push(sql`search_index.basic = 0`)
}

const raw = params.q?.trim()

Expand Down Expand Up @@ -151,6 +160,7 @@ export async function searchIndex(
search_index.price1,
search_index.basic,
search_index.preferred,
CASE WHEN search_index.preferred = 1 AND search_index.basic = 0 THEN 1 ELSE 0 END AS is_extended_promotional,
search_index.category,
search_index.subcategory
FROM search_index
Expand Down
12 changes: 11 additions & 1 deletion routes/api/search.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { sql } from "kysely"
import {
buildSearchTokenGroups,
type SearchTokenGroup,
buildSearchTokenGroups,
tokenizeSearchTerm,
} from "lib/util/search-token-groups"
import { withWinterSpec } from "lib/with-winter-spec"
Expand Down Expand Up @@ -50,6 +50,7 @@ export default withWinterSpec({
limit: z.string().optional(),
is_basic: z.boolean().optional(),
is_preferred: z.boolean().optional(),
is_extended_promotional: z.boolean().optional(),
}),
jsonResponse: z.any(),
} as const)(async (req, ctx) => {
Expand All @@ -58,6 +59,11 @@ export default withWinterSpec({
let query = ctx.db
.selectFrom("components")
.selectAll()
.select(
sql<number>`CASE WHEN preferred = 1 AND basic = 0 THEN 1 ELSE 0 END`.as(
"is_extended_promotional",
),
)
.limit(limit)
.orderBy("stock", "desc")
.where("stock", ">", 0)
Expand All @@ -72,6 +78,9 @@ export default withWinterSpec({
if (req.query.is_preferred) {
query = query.where("preferred", "=", 1)
}
if (req.query.is_extended_promotional) {
query = query.where("preferred", "=", 1).where("basic", "=", 0)
}

const baseQuery = query
let fallbackLikeTokens: string[] = []
Expand Down Expand Up @@ -193,6 +202,7 @@ export default withWinterSpec({
package: c.package,
is_basic: Boolean(c.basic),
is_preferred: Boolean(c.preferred),
is_extended_promotional: Boolean(c.is_extended_promotional),
description: c.description,
stock: c.stock,
price: extractSmallQuantityPrice(c.price),
Expand Down
22 changes: 21 additions & 1 deletion routes/components/list.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { sql } from "kysely"
import { Table } from "lib/ui/Table"
import { ExpressionBuilder } from "kysely"
import { Table } from "lib/ui/Table"
import { buildSearchTokenGroups } from "lib/util/search-token-groups"
import { withWinterSpec } from "lib/with-winter-spec"
import { z } from "zod"
Expand Down Expand Up @@ -35,6 +35,7 @@ export default withWinterSpec({
search: z.string().optional(),
is_basic: z.boolean().optional(),
is_preferred: z.boolean().optional(),
is_extended_promotional: z.boolean().optional(),
}),
jsonResponse: z.any(),
} as const)(async (req, ctx) => {
Expand All @@ -51,6 +52,10 @@ export default withWinterSpec({
"price",
"extra",
"basic",
"preferred",
sql<number>`CASE WHEN preferred = 1 AND basic = 0 THEN 1 ELSE 0 END`.as(
"is_extended_promotional",
),
])
.limit(limit)
.orderBy("stock", "desc")
Expand All @@ -70,6 +75,9 @@ export default withWinterSpec({
if (req.query.is_preferred) {
query = query.where("preferred", "=", 1)
}
if (req.query.is_extended_promotional) {
query = query.where("preferred", "=", 1).where("basic", "=", 0)
}

if (req.query.search) {
const search = req.query.search
Expand Down Expand Up @@ -111,6 +119,7 @@ export default withWinterSpec({
package: c.package,
is_basic: Boolean(c.basic),
is_preferred: Boolean(c.preferred),
is_extended_promotional: Boolean(c.is_extended_promotional),
description: c.description,
stock: c.stock,
price: extractSmallQuantityPrice(c.price),
Expand Down Expand Up @@ -155,6 +164,17 @@ export default withWinterSpec({
/>
</label>
</div>
<div>
<label>
Extended Promotional:
<input
type="checkbox"
name="is_extended_promotional"
value="true"
checked={req.query.is_extended_promotional}
/>
</label>
</div>
<button type="submit">Filter</button>
</form>

Expand Down
8 changes: 4 additions & 4 deletions scripts/setup-7z.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const BINARY_NAME = "7zz"

// Map of platform-arch combinations to download URLs
const BINARY_URLS: Record<string, string> = {
"linux-x64": "https://7-zip.org/a/7z2408-linux-x64.tar.xz",
"linux-arm64": "https://7-zip.org/a/7z2408-linux-arm64.tar.xz",
"darwin-x64": "https://7-zip.org/a/7z2408-mac.tar.xz",
"darwin-arm64": "https://7-zip.org/a/7z2408-mac.tar.xz",
"linux-x64": "https://7-zip.org/a/7z2601-linux-x64.tar.xz",
"linux-arm64": "https://7-zip.org/a/7z2601-linux-arm64.tar.xz",
"darwin-x64": "https://7-zip.org/a/7z2601-mac.tar.xz",
"darwin-arm64": "https://7-zip.org/a/7z2601-mac.tar.xz",
}

async function downloadAndExtract7z() {
Expand Down
8 changes: 5 additions & 3 deletions tests/preload.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { afterEach } from "bun:test"
import { setupDerivedTables } from "lib/db/derivedtables/setup-derived-tables"
import { getDbClient } from "lib/db/get-db-client"

declare global {
var deferredCleanupFns: Array<() => void | Promise<void>>
var derivedTablesSetupPromise: Promise<void> | undefined
}

globalThis.deferredCleanupFns ??= []
globalThis.derivedTablesSetupPromise ??= setupDerivedTables({ populate: false })
globalThis.derivedTablesSetupPromise ??= setupDerivedTables({
db: getDbClient(),
populate: false,
})

await globalThis.derivedTablesSetupPromise

Expand All @@ -20,5 +24,3 @@ afterEach(async () => {
await cleanup()
}
})

export {}
16 changes: 16 additions & 0 deletions tests/routes/api/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ test("GET /api/search with search query 'STM32F401RCT6' returns expected compone
expect(component).toHaveProperty("package")
expect(component).toHaveProperty("price")
expect(component).toHaveProperty("stock")
expect(component).toHaveProperty("is_extended_promotional")
})

test("GET /api/search filters extended promotional components", async () => {
const { axios } = await getTestServer()
const res = await axios.get(
"/api/search?limit=25&is_extended_promotional=true",
)

expect(res.data).toHaveProperty("components")
expect(Array.isArray(res.data.components)).toBe(true)
expect(
res.data.components.every(
(component: any) => component.is_extended_promotional === true,
),
).toBe(true)
})

test("GET /api/search with search query '555 Timer' returns expected components", async () => {
Expand Down
18 changes: 17 additions & 1 deletion tests/routes/components/list.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import { test, expect } from "bun:test"
import { expect, test } from "bun:test"
import { getTestServer } from "tests/fixtures/get-test-server"

test("GET /components/list with json param returns component data", async () => {
const { axios } = await getTestServer()
const res = await axios.get("/components/list?json=true")
expect(res.data).toHaveProperty("components")
expect(Array.isArray(res.data.components)).toBe(true)
expect(res.data.components.length).toBeGreaterThan(0)
expect(res.data.components[0]).toHaveProperty("is_extended_promotional")
})

test("GET /components/list filters extended promotional components", async () => {
const { axios } = await getTestServer()
const res = await axios.get(
"/components/list?json=true&is_extended_promotional=true",
)
expect(res.data).toHaveProperty("components")
expect(Array.isArray(res.data.components)).toBe(true)
expect(
res.data.components.every(
(component: any) => component.is_extended_promotional === true,
),
).toBe(true)
})
Loading