Initial commit: Apothecary v0.4.0

This commit is contained in:
2026-05-03 20:19:26 -04:00
commit 027cf032be
55 changed files with 14678 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
import { Router } from "express";
import { db } from "../db.js";
export const bootstrapRouter: Router = Router();
type ProductRow = {
id: string;
sku: string;
asset_tag: string | null;
name: string;
brand_id: string | null;
shop_id: string | null;
bin_id: string | null;
type: string;
kind: string;
weight: number;
last_audit_weight: number | null;
count_original: number;
count_last_audit: number | null;
unit_weight: number;
price: number;
thc: number;
cbd: number;
total_cannabinoids: number;
purchase_date: string;
status: string;
consumed_date: string | null;
gone_date: string | null;
rating: number | null;
notes: string | null;
strain_id: string | null;
};
type StrainRow = {
id: string;
name: string;
brand_id: string | null;
type: string;
default_thc: number | null;
default_cbd: number | null;
default_total_cannabinoids: number | null;
notes: string | null;
};
type AuditRow = {
id: number;
product_id: string;
date: string;
mode: string;
value: number;
prev_value: number | null;
confirmed_by: string | null;
};
bootstrapRouter.get("/bootstrap", (_req, res) => {
const products = db.prepare<[], ProductRow>("SELECT * FROM products ORDER BY id").all();
const audits = db
.prepare<[], AuditRow>("SELECT * FROM audits ORDER BY product_id, date")
.all();
const shops = db.prepare("SELECT * FROM shops ORDER BY id").all();
const brands = db.prepare("SELECT * FROM brands ORDER BY id").all();
const bins = db.prepare("SELECT * FROM bins ORDER BY id").all();
const strains = db
.prepare<[], StrainRow>("SELECT * FROM strains ORDER BY name COLLATE NOCASE")
.all();
const auditsByProduct = new Map<string, AuditRow[]>();
for (const a of audits) {
const arr = auditsByProduct.get(a.product_id) ?? [];
arr.push(a);
auditsByProduct.set(a.product_id, arr);
}
const productsOut = products.map((p) => ({
id: p.id,
sku: p.sku,
assetTag: p.asset_tag,
name: p.name,
brandId: p.brand_id,
shopId: p.shop_id,
binId: p.bin_id,
type: p.type,
kind: p.kind,
weight: p.weight,
lastAuditWeight: p.last_audit_weight,
countOriginal: p.count_original,
countLastAudit: p.count_last_audit,
unitWeight: p.unit_weight,
price: p.price,
thc: p.thc,
cbd: p.cbd,
totalCannabinoids: p.total_cannabinoids,
purchaseDate: p.purchase_date,
status: p.status,
consumedDate: p.consumed_date,
goneDate: p.gone_date,
rating: p.rating,
notes: p.notes,
strainId: p.strain_id,
audits: (auditsByProduct.get(p.id) ?? []).map((a) => ({
date: a.date,
mode: a.mode,
value: a.value,
prev: a.prev_value,
confirmedBy: a.confirmed_by,
})),
}));
const strainsOut = strains.map((s) => ({
id: s.id,
name: s.name,
brandId: s.brand_id,
type: s.type,
defaultThc: s.default_thc,
defaultCbd: s.default_cbd,
defaultTotalCannabinoids: s.default_total_cannabinoids,
notes: s.notes,
}));
res.json({
products: productsOut,
shops,
brands,
bins,
strains: strainsOut,
today: "2026-04-25",
});
});