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
10 changes: 8 additions & 2 deletions .github/workflows/bun-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
timeout-minutes: 60

steps:
- name: Checkout code
Expand All @@ -21,15 +21,21 @@ jobs:
- name: Install dependencies
run: bun install

- name: Install cf-proxy dependencies
working-directory: cf-proxy
run: bun install

- name: Cache setup artifacts
id: cache-setup
uses: actions/cache@v4
with:
path: ./db.sqlite3
key: db-sqlite3-${{ hashFiles('scripts/setup-*.ts') }}
restore-keys: |
db-sqlite3-

- name: Run setup if cache miss
if: steps.cache-setup.outputs.cache-hit != 'true'
if: steps.cache-setup.outputs.cache-hit != 'true' && hashFiles('db.sqlite3') == ''
run: bun run setup

- name: Run tests
Expand Down
2 changes: 2 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 @@ -34,6 +35,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
2 changes: 2 additions & 0 deletions cf-proxy/src/index.ts
Original file line number Diff line number Diff line change
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.preferred) && !Boolean(row.basic),
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.preferred) && !Boolean(row.basic),
})),
}

Expand Down
4 changes: 4 additions & 0 deletions cf-proxy/src/render.ts
Original file line number Diff line number Diff line change
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 @@ -540,6 +541,9 @@ const renderComponentsFilters = (
<input type="hidden" name="subcategory_name" value="${escapeHtml(params.subcategory_name ?? "")}" />
<input type="hidden" name="package" value="${escapeHtml(params.package ?? "")}" />
<input type="hidden" name="search" value="${escapeHtml(params.search ?? "")}" />
<div>
<label>Extended Promotional Part:<input type="checkbox" name="is_extended_promotional" value="true"${params.is_extended_promotional === "true" ? " checked" : ""} /></label>
</div>
<div>
<label>Basic Part:<input type="checkbox" name="is_basic" value="true"${params.is_basic === "true" ? " checked" : ""} /></label>
</div>
Expand Down
10 changes: 10 additions & 0 deletions cf-proxy/src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface SearchQueryParams {
limit?: string
is_basic?: string
is_preferred?: string
is_extended_promotional?: string
}

interface SearchRow {
Expand Down Expand Up @@ -110,6 +111,15 @@ export async function searchIndex(
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 AND COALESCE(search_index.basic, 0) = 0`,
)
}

const raw = params.q?.trim()

if (raw) {
Expand Down
23 changes: 23 additions & 0 deletions cf-proxy/test/render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,27 @@ describe("render helpers", () => {
"Feature&quot;:&quot;Overcurrent Protection(OCP)&quot;",
)
})

it("renders the extended promotional filter for the component catalog", () => {
const html = renderD1TablePage(
"/components/list",
{
components: [
{
lcsc: 123,
mfr: "ABC",
package: "0603",
is_extended_promotional: true,
},
],
},
{ is_extended_promotional: "true" },
"https://example.com/components/list?is_extended_promotional=true",
)

expect(html).toContain("Extended Promotional Part")
expect(html).toContain('name="is_extended_promotional"')
expect(html).toContain('is_extended_promotional" value="true" checked')
expect(html).toContain("Extended Promotional")
})
})
7 changes: 7 additions & 0 deletions routes/api/search.tsx
Original file line number Diff line number Diff line change
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 @@ -72,6 +73,11 @@ 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(sql<boolean>`COALESCE(basic, 0) = 0`)
}

const baseQuery = query
let fallbackLikeTokens: string[] = []
Expand Down Expand Up @@ -193,6 +199,7 @@ export default withWinterSpec({
package: c.package,
is_basic: Boolean(c.basic),
is_preferred: Boolean(c.preferred),
is_extended_promotional: Boolean(c.preferred) && !Boolean(c.basic),
description: c.description,
stock: c.stock,
price: extractSmallQuantityPrice(c.price),
Expand Down
19 changes: 19 additions & 0 deletions routes/components/list.tsx
Original file line number Diff line number Diff line change
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,7 @@ export default withWinterSpec({
"price",
"extra",
"basic",
"preferred",
])
.limit(limit)
.orderBy("stock", "desc")
Expand All @@ -70,6 +72,11 @@ 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(sql<boolean>`COALESCE(basic, 0) = 0`)
}

if (req.query.search) {
const search = req.query.search
Expand Down Expand Up @@ -111,6 +118,7 @@ export default withWinterSpec({
package: c.package,
is_basic: Boolean(c.basic),
is_preferred: Boolean(c.preferred),
is_extended_promotional: Boolean(c.preferred) && !Boolean(c.basic),
description: c.description,
stock: c.stock,
price: extractSmallQuantityPrice(c.price),
Expand All @@ -133,6 +141,17 @@ export default withWinterSpec({
/>
<input type="hidden" name="package" value={req.query.package ?? ""} />
<input type="hidden" name="search" value={req.query.search ?? ""} />
<div>
<label>
Extended Promotional Part:
<input
type="checkbox"
name="is_extended_promotional"
value="true"
checked={req.query.is_extended_promotional}
/>
</label>
</div>
<div>
<label>
Basic Part:
Expand Down
25 changes: 16 additions & 9 deletions scripts/setup-7z.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { mkdir, chmod } from "node:fs/promises"
import { mkdir, chmod, rename, rm } from "node:fs/promises"
import { existsSync } from "node:fs"
import { platform, arch } from "node:os"

const BINARY_DIR = ".bin"
const BINARY_NAME = "7zz"
const EXTRACT_DIR = ".buildtmp/7z"

// 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://github.com/ip7z/7zip/releases/download/26.01/7z2601-linux-x64.tar.xz",
"linux-arm64":
"https://github.com/ip7z/7zip/releases/download/26.01/7z2601-linux-arm64.tar.xz",
"darwin-x64":
"https://github.com/ip7z/7zip/releases/download/26.01/7z2601-mac.tar.xz",
"darwin-arm64":
"https://github.com/ip7z/7zip/releases/download/26.01/7z2601-mac.tar.xz",
}

async function downloadAndExtract7z() {
Expand Down Expand Up @@ -43,21 +48,23 @@ async function downloadAndExtract7z() {
}

// Save the tar.xz file
const tempFile = "7z-temp.tar.xz"
await rm(EXTRACT_DIR, { recursive: true, force: true })
await mkdir(EXTRACT_DIR, { recursive: true })
const tempFile = `${EXTRACT_DIR}/7z-temp.tar.xz`
await Bun.write(tempFile, await response.arrayBuffer())

// Extract the tar.xz file
console.log("Extracting 7z binary...")
await Bun.spawn(["tar", "xf", tempFile]).exited
await Bun.spawn(["tar", "xf", tempFile, "-C", EXTRACT_DIR]).exited

// Move the binary to the right location
await Bun.spawn(["mv", "7zz", binaryPath]).exited
await rename(`${EXTRACT_DIR}/${BINARY_NAME}`, binaryPath)

// Make the binary executable
await chmod(binaryPath, 0o755)

// Cleanup
await Bun.spawn(["rm", tempFile]).exited
await rm(EXTRACT_DIR, { recursive: true, force: true })

console.log("7z binary setup complete")
}
Expand Down
6 changes: 5 additions & 1 deletion 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 Down
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=50&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
3 changes: 3 additions & 0 deletions tests/routes/components/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ test("GET /components/list with json param returns component data", async () =>
const res = await axios.get("/components/list?json=true")
expect(res.data).toHaveProperty("components")
expect(Array.isArray(res.data.components)).toBe(true)
if (res.data.components.length > 0) {
expect(res.data.components[0]).toHaveProperty("is_extended_promotional")
}
})
Loading