server/models/index.ts
Rama main · réplica de lectura del repositorio original.
import * as path from 'path';
import {
DataSource,
type DataSourceOptions,
type EntityManager,
type EntityTarget,
type ObjectLiteral,
type Repository,
} from 'typeorm';
import { assert, makeLogger, panic } from '../helpers';
import AccessField from './entities/access-fields';
import Access from './entities/accesses';
import Account from './entities/accounts';
import Alert from './entities/alerts';
import AppliedRecurringTransaction from './entities/applied-recurring-transactions';
import Budget from './entities/budgets';
import Category from './entities/categories';
import DuplicatesIgnored from './entities/duplicates-ignored';
import RecurringTransaction from './entities/recurring-transactions';
import Setting from './entities/settings';
import TransactionRule from './entities/transaction-rule';
import TransactionRuleAction from './entities/transaction-rule-action';
import TransactionRuleCondition from './entities/transaction-rule-condition';
import Transaction from './entities/transactions';
import User from './entities/users';
import View from './entities/views';
type MinimalTransaction = Partial<Transaction> &
Pick<Transaction, 'date' | 'importDate' | 'amount' | 'rawLabel'>;
export {
Access,
AccessField,
Account,
Alert,
AppliedRecurringTransaction,
Budget,
Category,
DuplicatesIgnored,
type MinimalTransaction,
RecurringTransaction,
Setting,
Transaction,
TransactionRule,
TransactionRuleAction,
TransactionRuleCondition,
User,
View,
};
const log = makeLogger('models/index');
let dataSource: DataSource | null;
function makeOrmConfig(): DataSourceOptions {
let ormConfig: DataSourceOptions;
// Keep this switch in sync with ../config.ts!
switch (process.kresus.dbType) {
case 'sqlite':
assert(process.kresus.sqlitePath !== null, 'missing db path in server/models');
ormConfig = {
type: 'better-sqlite3',
database: process.kresus.sqlitePath,
logging: process.kresus.dbLog,
};
break;
case 'postgres':
assert(typeof process.kresus.dbHost === 'string', 'missing db host in server/models');
assert(typeof process.kresus.dbPort === 'number', 'missing db port in server/models');
assert(
typeof process.kresus.dbUsername === 'string',
'missing db username in server/models'
);
assert(
typeof process.kresus.dbPassword === 'string',
'missing db password in server/models'
);
assert(typeof process.kresus.dbName === 'string', 'missing db name in server/models');
ormConfig = {
type: process.kresus.dbType,
host: process.kresus.dbHost,
port: process.kresus.dbPort,
username: process.kresus.dbUsername,
password: process.kresus.dbPassword,
database: process.kresus.dbName,
logging: process.kresus.dbLog,
};
break;
default:
panic('unexpected db type in server/models');
}
return ormConfig;
}
export async function setupOrm(): Promise<DataSource> {
const ormConfig = Object.assign(makeOrmConfig(), {
// Automatically run migrations.
migrationsRun: true,
// Entity models.
entities: [path.join(__dirname, 'entities/*')],
// Subscribers.
subscribers: [path.join(__dirname, 'subscribers/*')],
// Migration files.
migrations: [path.join(__dirname, 'migrations/*')],
// Use one transaction by migration, avoiding issues on promises hanging after alter table.
migrationsTransactionMode: 'each',
// Automatically synchronize the database schema on startup. Very
// unsafe, use only to look at queries generated by the ORM.
synchronize: false,
});
dataSource = new DataSource(ormConfig);
await dataSource.initialize();
log.info('database is ready');
return dataSource;
}
export function getRepository<T extends ObjectLiteral>(x: EntityTarget<T>): Repository<T> {
if (dataSource === null || typeof dataSource === 'undefined') {
panic('Expected data source to be initialized');
}
return dataSource.getRepository(x);
}
export function getManager(): EntityManager {
if (dataSource === null || typeof dataSource === 'undefined') {
panic('Expected data source to be initialized');
}
return dataSource.manager;
}
export async function initModels() {
const { userLoginHttpHeader } = process.kresus;
dataSource = await setupOrm();
// Create default user.
let defaultUser: User | null;
if (process.kresus.providedUserId !== null) {
const userId = process.kresus.providedUserId;
// Check that the user actually exists already.
defaultUser = await User.find(userId);
if (!defaultUser) {
throw new Error(
`The user with provided ID ${userId} doesn't exist. Did you run "kresus create:user" first?`
);
}
} else {
const users: User[] = await User.all();
if (!users.length) {
const { login } = process.kresus.defaultUser;
assert(!!login, 'There should be a default login set!');
log.info('Creating default user as administrator...');
defaultUser = await User.create({ login, isAdmin: true });
} else if (users.length > 1 && !userLoginHttpHeader) {
throw new Error(
'Several users in database but "userLoginHttpHeader" was not configured. Please configure the userLoginHttpHeader variable in config.ini and setup a reverse proxy accordingly.'
);
} else {
defaultUser = users[0];
}
}
process.kresus.defaultUser = defaultUser;
log.info(
`Default user “${defaultUser.login}“ is set with id ${defaultUser.id} (admin: ${defaultUser.isAdmin})`
);
}