feat: manufacturer service with list, get, create

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 16:15:40 +02:00
parent 7de3e9e957
commit 8c1b19f07d
3 changed files with 117 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
import { asc, eq } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts";
import { manufacturers } from "../../db/schema.ts";
type Db = typeof prodDb;
export type CreateManufacturerInput = {
name: string;
slug: string;
website: string;
tier?: number;
country?: string;
};
export async function listManufacturers(db: Db = prodDb) {
return db.select().from(manufacturers).orderBy(asc(manufacturers.name));
}
export async function getManufacturerBySlug(db: Db = prodDb, slug: string) {
const [row] = await db
.select()
.from(manufacturers)
.where(eq(manufacturers.slug, slug));
return row ?? null;
}
export async function createManufacturer(
db: Db = prodDb,
data: CreateManufacturerInput,
) {
const [row] = await db
.insert(manufacturers)
.values({
name: data.name,
slug: data.slug,
website: data.website,
tier: data.tier ?? 1,
country: data.country ?? null,
})
.returning();
return row!;
}

View File

@@ -25,6 +25,8 @@ const TRUNCATE_TABLES = [
"setups", "setups",
"thread_candidates", "thread_candidates",
"threads", "threads",
"community_prices",
"market_prices",
"items", "items",
"global_item_tags", "global_item_tags",
"global_items", "global_items",
@@ -35,6 +37,7 @@ const TRUNCATE_TABLES = [
"api_keys", "api_keys",
"settings", "settings",
"categories", "categories",
"manufacturers",
"users", "users",
]; ];

View File

@@ -0,0 +1,72 @@
import { beforeEach, describe, expect, it } from "bun:test";
import { manufacturers } from "../../src/db/schema.ts";
import {
createManufacturer,
getManufacturerBySlug,
listManufacturers,
} from "../../src/server/services/manufacturer.service.ts";
import { createTestDb } from "../helpers/db.ts";
let db: Awaited<ReturnType<typeof createTestDb>>["db"];
beforeEach(async () => {
({ db } = await createTestDb());
});
describe("createManufacturer", () => {
it("inserts a manufacturer and returns it", async () => {
const result = await createManufacturer(db, {
name: "Apidura",
slug: "apidura",
website: "https://apidura.com",
tier: 1,
country: "GB",
});
expect(result.id).toBeGreaterThan(0);
expect(result.name).toBe("Apidura");
expect(result.slug).toBe("apidura");
expect(result.active).toBe(true);
});
it("throws on duplicate slug", async () => {
await createManufacturer(db, {
name: "Apidura",
slug: "apidura",
website: "https://apidura.com",
});
await expect(
createManufacturer(db, {
name: "Apidura Copy",
slug: "apidura",
website: "https://other.com",
}),
).rejects.toThrow();
});
});
describe("getManufacturerBySlug", () => {
it("returns manufacturer when found", async () => {
await createManufacturer(db, {
name: "Revelate Designs",
slug: "revelate-designs",
website: "https://revelatedesigns.com",
});
const result = await getManufacturerBySlug(db, "revelate-designs");
expect(result?.name).toBe("Revelate Designs");
});
it("returns null when not found", async () => {
const result = await getManufacturerBySlug(db, "nope");
expect(result).toBeNull();
});
});
describe("listManufacturers", () => {
it("returns all manufacturers ordered by name", async () => {
await createManufacturer(db, { name: "Ortlieb", slug: "ortlieb", website: "https://ortlieb.com" });
await createManufacturer(db, { name: "Apidura", slug: "apidura", website: "https://apidura.com" });
const result = await listManufacturers(db);
expect(result[0]?.name).toBe("Apidura");
expect(result[1]?.name).toBe("Ortlieb");
});
});