Initial commit
This commit is contained in:
Executable
+156
@@ -0,0 +1,156 @@
|
||||
import { Low } from 'lowdb';
|
||||
import { JSONFile } from 'lowdb/node';
|
||||
import { mkdirSync } from 'fs';
|
||||
import { dirname } from 'path';
|
||||
|
||||
const DB_PATH = process.env.DB_PATH || './data/budget.json';
|
||||
|
||||
const DEFAULT = {
|
||||
categories: [
|
||||
{ id: 1, name: 'Kivra', sort_order: 1, color: '#7C3AED' },
|
||||
{ id: 2, name: 'eFaktura', sort_order: 2, color: '#2563EB' },
|
||||
{ id: 3, name: 'Manuella', sort_order: 3, color: '#D97706' },
|
||||
{ id: 4, name: 'Autogiro', sort_order: 4, color: '#059669' },
|
||||
],
|
||||
months: [],
|
||||
income: [],
|
||||
bills: [],
|
||||
subscriptions: [],
|
||||
loans: [],
|
||||
payments: [],
|
||||
banking: {
|
||||
enable_banking: {
|
||||
enabled: false,
|
||||
status: 'not_connected',
|
||||
institution: '',
|
||||
last_sync_at: null,
|
||||
notes: '',
|
||||
application_id: '',
|
||||
private_key_pem: '',
|
||||
redirect_url: '',
|
||||
country: 'SE',
|
||||
psu_type: 'personal',
|
||||
auto_sync_enabled: false,
|
||||
sync_interval_minutes: 360,
|
||||
import_from_date: null,
|
||||
incremental_sync_days: 7,
|
||||
pending_state: null,
|
||||
last_callback_at: null,
|
||||
last_callback_url: '',
|
||||
last_callback_code_present: false,
|
||||
last_callback_state: '',
|
||||
last_callback_exchange_at: null,
|
||||
last_callback_exchange_error: '',
|
||||
session_id: null,
|
||||
session_expires_at: null,
|
||||
session_created_at: null,
|
||||
account_aliases: {},
|
||||
transaction_categories: {},
|
||||
accounts: [],
|
||||
transactions: [],
|
||||
last_sync_summary: null,
|
||||
last_error: null,
|
||||
},
|
||||
},
|
||||
auth: {
|
||||
settings: {
|
||||
enabled: false,
|
||||
issuer: '',
|
||||
discovery_url: '',
|
||||
client_id: '',
|
||||
client_secret: '',
|
||||
redirect_uri: '',
|
||||
scope: 'openid profile email groups',
|
||||
session_secret: '',
|
||||
allowed_groups: '',
|
||||
allowed_emails: '',
|
||||
allowed_domains: '',
|
||||
session_ttl_hours: 12,
|
||||
},
|
||||
sessions: [],
|
||||
pending: [],
|
||||
},
|
||||
ai: {
|
||||
ollama: {
|
||||
enabled: false,
|
||||
base_url: 'http://host.docker.internal:11434',
|
||||
model: '',
|
||||
vision_model: '',
|
||||
system_prompt: '',
|
||||
include_budget_context: true,
|
||||
include_banking_context: true,
|
||||
},
|
||||
conversations: [],
|
||||
},
|
||||
app_settings: {
|
||||
finance_profile: {
|
||||
salary_day_of_month: 25,
|
||||
buffer_days_target: 7,
|
||||
salary_account_uid: '',
|
||||
recurring_income_note: '',
|
||||
},
|
||||
account_view: {
|
||||
primary_account_uid: '',
|
||||
include_savings_in_ai: false,
|
||||
hide_zero_balance_accounts: false,
|
||||
},
|
||||
notifications: {
|
||||
ntfy_enabled: false,
|
||||
ntfy_base_url: 'https://ntfy.sh',
|
||||
ntfy_topic: '',
|
||||
ntfy_access_token: '',
|
||||
ntfy_title: 'Enkelbudget',
|
||||
ntfy_tags: 'money_with_wings,bank',
|
||||
ntfy_click_url: '',
|
||||
ntfy_priority: 3,
|
||||
notify_new_transactions: true,
|
||||
include_pending_transactions: false,
|
||||
minimum_transaction_amount: 0,
|
||||
last_error: '',
|
||||
last_sent_at: null,
|
||||
},
|
||||
},
|
||||
_seq: { categories: 4, months: 0, income: 0, bills: 0, subscriptions: 0, loans: 0, payments: 0 },
|
||||
};
|
||||
|
||||
let _db = null;
|
||||
|
||||
export async function getDb() {
|
||||
if (!_db) {
|
||||
mkdirSync(dirname(DB_PATH), { recursive: true });
|
||||
const adapter = new JSONFile(DB_PATH);
|
||||
_db = new Low(adapter, DEFAULT);
|
||||
await _db.read();
|
||||
_db.data ||= structuredClone(DEFAULT);
|
||||
_db.data.categories ||= structuredClone(DEFAULT.categories);
|
||||
_db.data.months ||= [];
|
||||
_db.data.income ||= [];
|
||||
_db.data.bills ||= [];
|
||||
_db.data.subscriptions ||= [];
|
||||
_db.data.loans ||= [];
|
||||
_db.data.payments ||= [];
|
||||
_db.data.banking ||= structuredClone(DEFAULT.banking);
|
||||
_db.data.banking.enable_banking ||= structuredClone(DEFAULT.banking.enable_banking);
|
||||
_db.data.auth ||= structuredClone(DEFAULT.auth);
|
||||
_db.data.auth.settings ||= structuredClone(DEFAULT.auth.settings);
|
||||
_db.data.auth.sessions ||= [];
|
||||
_db.data.auth.pending ||= [];
|
||||
_db.data.ai ||= structuredClone(DEFAULT.ai);
|
||||
_db.data.ai.ollama ||= structuredClone(DEFAULT.ai.ollama);
|
||||
_db.data.ai.conversations ||= [];
|
||||
_db.data.app_settings ||= structuredClone(DEFAULT.app_settings);
|
||||
_db.data.app_settings.finance_profile ||= structuredClone(DEFAULT.app_settings.finance_profile);
|
||||
_db.data.app_settings.account_view ||= structuredClone(DEFAULT.app_settings.account_view);
|
||||
_db.data.app_settings.notifications ||= structuredClone(DEFAULT.app_settings.notifications);
|
||||
_db.data._seq ||= {};
|
||||
for (const [key, value] of Object.entries(DEFAULT._seq)) {
|
||||
_db.data._seq[key] ??= value;
|
||||
}
|
||||
}
|
||||
return _db;
|
||||
}
|
||||
|
||||
export function nextId(db, table) {
|
||||
db.data._seq[table] = (db.data._seq[table] ?? 0) + 1;
|
||||
return db.data._seq[table];
|
||||
}
|
||||
Reference in New Issue
Block a user