Implement local SQLite backend and reactive UI
This commit is contained in:
@@ -1,16 +1,50 @@
|
||||
import type { Db } from "../db/database.js";
|
||||
import { getModel, updateModelCell } from "../db/queries.js";
|
||||
import { ok } from "./result.js";
|
||||
import { createModelRow, deleteModelRow, getModel, resolveCompany, updateModelCell } from "../db/queries.js";
|
||||
import { fail, ok } from "./result.js";
|
||||
import type { RpcHandlers } from "./types.js";
|
||||
|
||||
export function modelHandlers(db: Db): RpcHandlers<"model.get" | "model.updateCell" | "model.runScenario"> {
|
||||
function errorDetail(operation: string, error: unknown): { operation: string; message?: string } {
|
||||
return {
|
||||
"model.get": ({ companyId, tab }) => ok("model.get", getModel(db, companyId, tab)),
|
||||
"model.updateCell": ({ companyId, tab, row, col, value }) =>
|
||||
ok("model.updateCell", updateModelCell(db, companyId, tab, row, col, value)),
|
||||
"model.runScenario": ({ companyId }) => {
|
||||
const model = getModel(db, companyId, "income");
|
||||
return ok("model.runScenario", model);
|
||||
operation,
|
||||
message: error instanceof Error ? error.message : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function modelHandlers(db: Db): RpcHandlers<"model.get" | "model.updateCell" | "model.createRow" | "model.deleteRow" | "model.runScenario"> {
|
||||
return {
|
||||
"model.get": ({ companyId, tab }) => {
|
||||
const company = resolveCompany(db, companyId);
|
||||
if (!company) return fail("NOT_FOUND", `Company "${companyId}" not found.`);
|
||||
try {
|
||||
return ok("model.get", getModel(db, company.id, tab));
|
||||
} catch (error) {
|
||||
return fail("INTERNAL_ERROR", "Could not load model for company.", errorDetail("getModel", error));
|
||||
}
|
||||
},
|
||||
"model.updateCell": ({ companyId, tab, row, col, value }) => {
|
||||
const company = resolveCompany(db, companyId);
|
||||
if (!company) return fail("NOT_FOUND", `Company "${companyId}" not found.`);
|
||||
return ok("model.updateCell", updateModelCell(db, company.id, tab, row, col, value));
|
||||
},
|
||||
"model.createRow": ({ companyId, tab, label, kind, values }) => {
|
||||
const company = resolveCompany(db, companyId);
|
||||
if (!company) return fail("NOT_FOUND", `Company "${companyId}" not found.`);
|
||||
return ok("model.createRow", createModelRow(db, company.id, tab, { label, kind, values: values ?? [] }));
|
||||
},
|
||||
"model.deleteRow": ({ companyId, tab, row }) => {
|
||||
const company = resolveCompany(db, companyId);
|
||||
if (!company) return fail("NOT_FOUND", `Company "${companyId}" not found.`);
|
||||
return ok("model.deleteRow", { ok: deleteModelRow(db, company.id, tab, row) });
|
||||
},
|
||||
"model.runScenario": ({ companyId, overrides }) => {
|
||||
const company = resolveCompany(db, companyId);
|
||||
if (!company) return fail("NOT_FOUND", `Company "${companyId}" not found.`);
|
||||
const model = getModel(db, company.id, "operating");
|
||||
const rows = model.rows.map((row, rowIndex) => ({
|
||||
...row,
|
||||
values: row.values.map((value, colIndex) => overrides[`${rowIndex}-${colIndex}`] ?? value),
|
||||
}));
|
||||
return ok("model.runScenario", { headers: model.headers, rows });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user