zmiany cd

This commit is contained in:
Mateusz Gruszczyński
2026-04-06 15:38:16 +02:00
parent 80e181ea3f
commit a8e497fec3
17 changed files with 555 additions and 11315 deletions

51
api/package-lock.json generated
View File

@@ -604,6 +604,9 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -618,6 +621,9 @@
"arm"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -632,6 +638,9 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -646,6 +655,9 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -660,6 +672,9 @@
"loong64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -674,6 +689,9 @@
"loong64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -688,6 +706,9 @@
"ppc64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -702,6 +723,9 @@
"ppc64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -716,6 +740,9 @@
"riscv64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -730,6 +757,9 @@
"riscv64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -744,6 +774,9 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -758,6 +791,9 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -772,6 +808,9 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -1731,9 +1770,9 @@
}
},
"node_modules/dotenv": {
"version": "17.4.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.0.tgz",
"integrity": "sha512-kCKF62fwtzwYm0IGBNjRUjtJgMfGapII+FslMHIjMR5KTnwEmBmWLDRSnc3XSNP8bNy34tekgQyDT0hr7pERRQ==",
"version": "17.4.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz",
"integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -3905,9 +3944,9 @@
}
},
"node_modules/vite": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
"integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@@ -1,8 +1,16 @@
import type { Response } from 'express';
import { createRequire } from 'node:module';
import path from 'node:path';
import process from 'node:process';
import { z } from 'zod';
import { AppDataSource } from '../config/data-source.js';
import { env } from '../config/env.js';
import { AppSetting } from '../entities/AppSetting.js';
import { Budget } from '../entities/Budget.js';
import { Category } from '../entities/Category.js';
import { Expense } from '../entities/Expense.js';
import { Merchant } from '../entities/Merchant.js';
import { RecurringExpense } from '../entities/RecurringExpense.js';
import { User } from '../entities/User.js';
import { sanitizeUser } from '../services/auth.service.js';
import type { AuthenticatedRequest } from '../types/express.js';
@@ -30,8 +38,17 @@ const userUpdateSchema = z.object({
});
const require = createRequire(import.meta.url);
const rootPackage = require(path.resolve(process.cwd(), '..', 'package.json')) as { version?: string };
const apiPackage = require(path.resolve(process.cwd(), 'package.json')) as { version?: string };
const webPackage = require(path.resolve(process.cwd(), '..', 'web', 'package.json')) as { version?: string };
const settingsRepo = () => AppDataSource.getRepository(AppSetting);
const userRepo = () => AppDataSource.getRepository(User);
const expenseRepo = () => AppDataSource.getRepository(Expense);
const categoryRepo = () => AppDataSource.getRepository(Category);
const merchantRepo = () => AppDataSource.getRepository(Merchant);
const budgetRepo = () => AppDataSource.getRepository(Budget);
const recurringRepo = () => AppDataSource.getRepository(RecurringExpense);
const sanitizeSettings = (item: AppSetting) => ({
id: item.id,
@@ -145,3 +162,39 @@ export const testSmtp = async (req: AuthenticatedRequest, res: Response) => {
return res.json({ message: 'SMTP test message was sent' });
};
export const getSystemInfo = async (_req: AuthenticatedRequest, res: Response) => {
const settings = await getSettingsEntity();
const [users, expenses, categories, merchants, budgets, recurring, usersWithIntegrations] = await Promise.all([
userRepo().count(),
expenseRepo().count(),
categoryRepo().count(),
merchantRepo().count(),
budgetRepo().count(),
recurringRepo().count(),
userRepo().find({ select: { id: true, shoppingListIntegration: true } })
]);
const shoppingIntegrations = usersWithIntegrations.filter((user) => Boolean(user.shoppingListIntegration?.enabled)).length;
return res.json({
item: {
appName: settings?.appName ?? 'Expense Control',
suiteVersion: rootPackage.version ?? '0.0.0',
apiVersion: apiPackage.version ?? '0.0.0',
webVersion: webPackage.version ?? '0.0.0',
nodeVersion: process.version,
environment: process.env.NODE_ENV ?? 'development',
database: env.DB_TYPE,
uploadDir: env.UPLOAD_DIR,
registrationEnabled: settings?.registrationEnabled ?? true,
smtpConfigured: Boolean(settings?.smtpEnabled && settings?.smtpHost && settings?.smtpFromEmail),
counters: { users, expenses, categories, merchants, budgets, recurring, shoppingIntegrations },
sources: {
appRepository: 'https://git.linuxiarz.pl/gru/expense-control',
shoppingListRepository: 'https://git.linuxiarz.pl/gru/lista_zakupowa_live',
apiBasePath: '/api'
},
checkedAt: new Date().toISOString()
}
});
};

View File

@@ -1,6 +1,7 @@
import { Router } from 'express';
import {
getSettings,
getSystemInfo,
listUsers,
testSmtp,
updateSettings,
@@ -16,3 +17,4 @@ adminRouter.put('/settings', updateSettings);
adminRouter.get('/users', listUsers);
adminRouter.patch('/users/:id', updateUser);
adminRouter.post('/test-smtp', testSmtp);
adminRouter.get('/system-info', getSystemInfo);