fix docker build

This commit is contained in:
Mateusz Gruszczyński
2026-04-06 16:41:32 +02:00
parent 723e3441df
commit 3f130ad9ed
10 changed files with 59 additions and 43 deletions

View File

@@ -3,6 +3,7 @@ import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { createRequire } from 'node:module';
import { z } from 'zod';
import { AppDataSource } from '../config/data-source.js';
import { env } from '../config/env.js';
@@ -38,42 +39,53 @@ const userUpdateSchema = z.object({
defaultCurrency: z.string().min(3).max(8).optional()
});
type PackageJson = { version?: string };
const require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const readPackageJsonSafe = (filePath: string | null): PackageJson | null => {
if (!filePath || !fs.existsSync(filePath)) return null;
type PackageLike = { version?: string };
function readPackageJsonSafe(filePath: string): PackageLike | null {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as PackageJson;
if (!fs.existsSync(filePath)) return null;
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as PackageLike;
} catch {
return null;
}
};
}
const findNearestPackageJson = (startDir: string): string | null => {
let currentDir = path.resolve(startDir);
function findApiPackage(): PackageLike | null {
return (
readPackageJsonSafe(path.resolve(__dirname, '../../package.json')) ??
readPackageJsonSafe(path.resolve(__dirname, '../package.json'))
);
}
while (true) {
const candidate = path.join(currentDir, 'package.json');
if (fs.existsSync(candidate)) return candidate;
const parentDir = path.dirname(currentDir);
if (parentDir == currentDir) return null;
currentDir = parentDir;
function findRootPackage(): PackageLike | null {
const candidates = [
path.resolve(__dirname, '../../../package.json'),
path.resolve(__dirname, '../../package.json'),
path.resolve(__dirname, '../package.json')
];
for (const candidate of candidates) {
const pkg = readPackageJsonSafe(candidate);
if (!pkg) continue;
if (candidate.endsWith('/api/package.json') || candidate.endsWith('\\api\\package.json')) continue;
return pkg;
}
};
return null;
}
const apiPackagePath = findNearestPackageJson(__dirname);
const apiPackage = readPackageJsonSafe(apiPackagePath);
const apiRootDir = apiPackagePath ? path.dirname(apiPackagePath) : null;
const projectRootPackagePath = apiRootDir ? findNearestPackageJson(path.dirname(apiRootDir)) : null;
const rootPackage = readPackageJsonSafe(projectRootPackagePath);
const webPackage = readPackageJsonSafe(
projectRootPackagePath ? path.join(path.dirname(projectRootPackagePath), 'web', 'package.json') : null
);
function findWebPackage(): PackageLike | null {
return (
readPackageJsonSafe(path.resolve(__dirname, '../../../web/package.json')) ??
readPackageJsonSafe(path.resolve(__dirname, '../../web/package.json'))
);
}
const rootPackage = findRootPackage();
const apiPackage = findApiPackage();
const webPackage = findWebPackage();
const settingsRepo = () => AppDataSource.getRepository(AppSetting);
const userRepo = () => AppDataSource.getRepository(User);

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { Category } from './Category.js';
import { User } from './User.js';
import { decimalTransformer } from '../utils/decimal.js';
@@ -31,8 +32,8 @@ export class Budget {
updatedAt!: Date;
@ManyToOne(() => User, { onDelete: 'CASCADE' })
user!: User;
user!: Relation<User>;
@ManyToOne(() => Category, { eager: true, nullable: true, onDelete: 'SET NULL' })
category!: Category | null;
category!: Relation<Category> | null;
}

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { Expense } from './Expense.js';
import { User } from './User.js';
import { dateTimeColumnType } from '../utils/db-column-types.js';
@@ -21,8 +22,8 @@ export class Category {
createdAt!: Date;
@ManyToOne(() => User, (user) => user.categories, { nullable: true, onDelete: 'CASCADE' })
user!: User | null;
user!: Relation<User> | null;
@OneToMany(() => Expense, (expense) => expense.category)
expenses!: Expense[];
expenses!: Relation<Expense[]>;
}

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { Category } from './Category.js';
import { Proof } from './Proof.js';
import { User } from './User.js';
@@ -62,11 +63,11 @@ export class Expense {
updatedAt!: Date;
@ManyToOne(() => User, (user) => user.expenses, { onDelete: 'CASCADE' })
user!: User;
user!: Relation<User>;
@ManyToOne(() => Category, (category) => category.expenses, { eager: true, onDelete: 'RESTRICT' })
category!: Category;
category!: Relation<Category>;
@OneToMany(() => Proof, (proof) => proof.expense, { eager: true, cascade: true })
proofs!: Proof[];
proofs!: Relation<Proof[]>;
}

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { User } from './User.js';
import { dateTimeColumnType } from '../utils/db-column-types.js';
@@ -26,5 +27,5 @@ export class Merchant {
updatedAt!: Date;
@ManyToOne(() => User, { onDelete: 'CASCADE' })
user!: User;
user!: Relation<User>;
}

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { Expense } from './Expense.js';
import { dateTimeColumnType } from '../utils/db-column-types.js';
@@ -34,5 +35,5 @@ export class Proof {
createdAt!: Date;
@ManyToOne(() => Expense, (expense) => expense.proofs, { onDelete: 'CASCADE' })
expense!: Expense;
expense!: Relation<Expense>;
}

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { Category } from './Category.js';
import { User } from './User.js';
import { decimalTransformer } from '../utils/decimal.js';
@@ -72,8 +73,8 @@ export class RecurringExpense {
updatedAt!: Date;
@ManyToOne(() => User, { onDelete: 'CASCADE' })
user!: User;
user!: Relation<User>;
@ManyToOne(() => Category, { eager: true, onDelete: 'RESTRICT' })
category!: Category;
category!: Relation<Category>;
}

View File

@@ -1,4 +1,5 @@
import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import type { Relation } from 'typeorm';
import { Category } from './Category.js';
import { Expense } from './Expense.js';
import { dateTimeColumnType } from '../utils/db-column-types.js';
@@ -51,8 +52,8 @@ export class User {
createdAt!: Date;
@OneToMany(() => Category, (category) => category.user)
categories!: Category[];
categories!: Relation<Category[]>;
@OneToMany(() => Expense, (expense) => expense.user)
expenses!: Expense[];
expenses!: Relation<Expense[]>;
}

View File

@@ -1,5 +1,2 @@
import type { ColumnType } from 'typeorm';
const dbType = (process.env.DB_TYPE ?? 'sqlite').toLowerCase();
export const dateTimeColumnType: ColumnType = dbType === 'postgres' ? 'timestamp' : 'datetime';
export const dateTimeColumnType: 'timestamp' | 'datetime' =
process.env.DB_TYPE === 'postgres' ? 'timestamp' : 'datetime';

View File

@@ -34,7 +34,7 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "1MB",
"maximumWarning": "1.5MB",
"maximumError": "2MB"
}
],