import chalk from 'chalk'; import LibDashStore from 'libdashstore'; import { MssqlProvider } from 'libdashstore/providers/mssql'; import { BetterSqlite3Provider } from 'libdashstore/providers/better-sqlite3'; import env from '../config/env.js'; let provider; let store; let connecting; const STORE_NAMESPACES = [ 'companyuser', 'company', 'category', 'article', 'pic', 'unit', 'brand', 'lang', 'tax', 'google_auth', 'posterminal', 'supplier', 'delivery', 'customergroup', 'entity', 'entityaddress', 'entitycontact', 'quote', 'order', 'numbers', 'companysetting', 'articlesupplier', 'manifestattachment', 'ledger', 'warehouse', 'printer', 'labeltemplate', 'stock', 'propertyname', 'articleproperty', 'attributename', 'attributevalue', 'articleattributevalue', ]; /** * Wraps LibDashStore namespace methods so each call logs its duration. * @param {InstanceType} rawStore * @returns {InstanceType} */ function wrapStoreWithTiming(rawStore) { for (const namespace of STORE_NAMESPACES) { const api = rawStore[namespace]; if (!api || typeof api !== 'object') continue; for (const [method, fn] of Object.entries(api)) { if (typeof fn !== 'function') continue; api[method] = async (...args) => { const start = Date.now(); try { const result = await fn(...args); console.log( `${chalk.magenta('libstore')} ${namespace}.${method} ${chalk.gray(`(${Date.now() - start}ms)`)}` ); return result; } catch (err) { console.error( `${chalk.magenta('libstore')} ${namespace}.${method} ${chalk.red('FAILED')} ` + `${chalk.gray(`(${Date.now() - start}ms)`)} ${chalk.red(err.message)}` ); throw err; } }; } } for (const method of ['purge']) { const fn = rawStore[method]; if (typeof fn !== 'function') continue; rawStore[method] = async (...args) => { const start = Date.now(); try { return await fn(...args); } finally { const duration = Date.now() - start; console.log(`${chalk.magenta('libstore')} ${method} ${chalk.gray(`(${duration}ms)`)}`); } }; } return rawStore; } function getMssqlConfig() { const { server, database, user, password, port, encrypt, trustServerCertificate } = env.mssql; if (!server || !database || !user || !password) { throw new Error('MSSQL is not configured (MSSQL_SERVER, MSSQL_DATABASE, MSSQL_USER, MSSQL_PASSWORD required)'); } return { server, database, user, password, port, pool: { max: 10, min: 0, idleTimeoutMillis: 30_000, }, options: { encrypt, trustServerCertificate, }, }; } /** * Returns the initialized LibDashStore singleton. * @returns {Promise>} */ export async function getStore() { if (store) { return store; } if (!connecting) { connecting = (async () => { if (env.dbProvider === 'sqlite' || env.dbProvider === 'better-sqlite3') { provider = new BetterSqlite3Provider(env.sqlite); } else { provider = new MssqlProvider(getMssqlConfig()); } await provider.initialize(); store = wrapStoreWithTiming(await new LibDashStore(provider)); return store; })().finally(() => { connecting = undefined; }); } return connecting; } export async function ensureConnection() { await getStore(); } export async function closeStore() { if (provider) { await provider.close(); provider = undefined; store = undefined; } }