SettingsHelper
This commit is contained in:
parent
f850fc2526
commit
f32143b7ac
15 changed files with 199 additions and 49 deletions
|
@ -1,7 +1,7 @@
|
|||
import "dotenv/config";
|
||||
import "reflect-metadata";
|
||||
import { DataSource } from "typeorm";
|
||||
import { DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME, DB_TYPE, DB_PORT } from "./env.defaults";
|
||||
import { SettingHelper } from "./helpers/settingsHelper";
|
||||
|
||||
import { user } from "./entity/management/user";
|
||||
import { refresh } from "./entity/refresh";
|
||||
|
@ -53,12 +53,12 @@ import { NewsletterColumnType1744351418751 } from "./migrations/1744351418751-ne
|
|||
import { QueryUpdatedAt1744795756230 } from "./migrations/1744795756230-QueryUpdatedAt";
|
||||
|
||||
const dataSource = new DataSource({
|
||||
type: DB_TYPE as any,
|
||||
host: DB_HOST,
|
||||
port: DB_PORT,
|
||||
username: DB_USERNAME,
|
||||
password: DB_PASSWORD,
|
||||
database: DB_NAME,
|
||||
type: SettingHelper.getEnvSetting("database.type") as any,
|
||||
host: SettingHelper.getEnvSetting("database.host"),
|
||||
port: Number(SettingHelper.getEnvSetting("database.port")),
|
||||
username: SettingHelper.getEnvSetting("database.username"),
|
||||
password: SettingHelper.getEnvSetting("database.password"),
|
||||
database: SettingHelper.getEnvSetting("database.name"),
|
||||
synchronize: false,
|
||||
logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"],
|
||||
bigNumberStrings: false,
|
||||
|
|
13
src/entity/management/settings.ts
Normal file
13
src/entity/management/settings.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { Column, Entity, PrimaryColumn } from "typeorm";
|
||||
|
||||
@Entity()
|
||||
export class user {
|
||||
@PrimaryColumn({ type: "varchar", length: 255 })
|
||||
topic: string;
|
||||
|
||||
@PrimaryColumn({ type: "varchar", length: 255 })
|
||||
key: string;
|
||||
|
||||
@Column({ type: "varchar", length: 255 })
|
||||
value: string;
|
||||
}
|
|
@ -2,15 +2,6 @@ import "dotenv/config";
|
|||
import ms from "ms";
|
||||
import ip from "ip";
|
||||
|
||||
export const DB_TYPE = process.env.DB_TYPE ?? "mysql";
|
||||
export const DB_HOST = process.env.DB_HOST ?? "";
|
||||
export const DB_PORT = Number(process.env.DB_PORT ?? 3306);
|
||||
export const DB_NAME = process.env.DB_NAME ?? "";
|
||||
export const DB_USERNAME = process.env.DB_USERNAME ?? "";
|
||||
export const DB_PASSWORD = process.env.DB_PASSWORD ?? "";
|
||||
|
||||
export const SERVER_PORT = Number(process.env.SERVER_PORT ?? 5000);
|
||||
|
||||
export const JWT_SECRET = process.env.JWT_SECRET ?? "my_jwt_secret_string_ilughfnadiuhgq§$IUZGFVRweiouarbt1oub3h5q4a";
|
||||
export const JWT_EXPIRATION = (process.env.JWT_EXPIRATION ?? "15m") as ms.StringValue;
|
||||
export const REFRESH_EXPIRATION = (process.env.REFRESH_EXPIRATION ?? "1d") as ms.StringValue;
|
||||
|
@ -27,7 +18,6 @@ export const CLUB_WEBSITE = process.env.CLUB_WEBSITE ?? "";
|
|||
|
||||
export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "1");
|
||||
export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "7");
|
||||
export const BACKUP_AUTO_RESTORE = process.env.BACKUP_AUTO_RESTORE ?? "true";
|
||||
|
||||
export const USE_SECURITY_STRICT_LIMIT = process.env.USE_SECURITY_STRICT_LIMIT ?? "true";
|
||||
export const SECURITY_STRICT_LIMIT_WINDOW = (process.env.SECURITY_STRICT_LIMIT_WINDOW ?? "15m") as ms.StringValue;
|
||||
|
@ -55,18 +45,6 @@ export const TRUST_PROXY = ((): Array<string> | string | boolean | number | null
|
|||
})();
|
||||
|
||||
export function configCheck() {
|
||||
if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres")
|
||||
throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)");
|
||||
if ((DB_HOST == "" || typeof DB_HOST != "string") && DB_TYPE != "sqlite")
|
||||
throw new Error("set valid value to DB_HOST");
|
||||
if (DB_NAME == "" || typeof DB_NAME != "string") throw new Error("set valid value to DB_NAME");
|
||||
if ((DB_USERNAME == "" || typeof DB_USERNAME != "string") && DB_TYPE != "sqlite")
|
||||
throw new Error("set valid value to DB_USERNAME");
|
||||
if ((DB_PASSWORD == "" || typeof DB_PASSWORD != "string") && DB_TYPE != "sqlite")
|
||||
throw new Error("set valid value to DB_PASSWORD");
|
||||
|
||||
if (isNaN(SERVER_PORT)) throw new Error("set valid numeric value to SERVER_PORT");
|
||||
|
||||
if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET");
|
||||
checkMS(JWT_EXPIRATION, "JWT_EXPIRATION");
|
||||
checkMS(REFRESH_EXPIRATION, "REFRESH_EXPIRATION");
|
||||
|
@ -84,8 +62,6 @@ export function configCheck() {
|
|||
)
|
||||
throw new Error("CLUB_WEBSITE is not valid url");
|
||||
|
||||
if (BACKUP_AUTO_RESTORE != "true" && BACKUP_AUTO_RESTORE != "false")
|
||||
throw new Error("set 'true' or 'false' to BACKUP_AUTO_RESTORE");
|
||||
if (BACKUP_INTERVAL < 1) throw new Error("BACKUP_INTERVAL has to be at least 1");
|
||||
if (BACKUP_COPIES < 1) throw new Error("BACKUP_COPIES has to be at least 1");
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { DB_TYPE } from "../../../../env.defaults";
|
||||
import { SettingHelper } from "../../../../helpers/settingsHelper";
|
||||
|
||||
export default abstract class DateMappingHelper {
|
||||
static mapDate(entry: any) {
|
||||
switch (DB_TYPE) {
|
||||
switch (SettingHelper.getEnvSetting("database.type")) {
|
||||
case "postgres":
|
||||
return `${entry?.years ?? 0} years ${entry?.months ?? 0} months ${entry?.days ?? 0} days`;
|
||||
case "mysql":
|
||||
|
|
57
src/helpers/settingsHelper.ts
Normal file
57
src/helpers/settingsHelper.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
import ms from "ms";
|
||||
import { EnvSettingString, envSettingsType, SettingString, settingsType } from "../type/settingTypes";
|
||||
|
||||
export abstract class SettingHelper {
|
||||
private static settings: { [key in SettingString]?: string } = {};
|
||||
private static envSettings: { [key in EnvSettingString]?: string } = {};
|
||||
|
||||
public static getSetting(key: SettingString): string | number | boolean | ms.StringValue {
|
||||
let settingType = settingsType[key];
|
||||
return this.settings[key] ?? settingType.default ?? "";
|
||||
}
|
||||
|
||||
public static getEnvSetting(key: EnvSettingString): string {
|
||||
let settingType = envSettingsType[key];
|
||||
return this.envSettings[key] ?? settingType.default ?? "";
|
||||
}
|
||||
|
||||
public static async configure() {}
|
||||
|
||||
public static async configurEnv() {
|
||||
this.envSettings = {
|
||||
"database.type": process.env.DB_TYPE,
|
||||
"database.host": process.env.DB_HOST,
|
||||
"database.port": process.env.DB_PORT,
|
||||
"database.name": process.env.DB_NAME,
|
||||
"database.username": process.env.DB_USERNAME,
|
||||
"database.password": process.env.DB_PASSWORD,
|
||||
};
|
||||
this.checkEnvSettings();
|
||||
}
|
||||
|
||||
private static checkEnvSettings() {
|
||||
if (!["mysql", "sqlite", "postgres"].includes(this.envSettings["database.type"]))
|
||||
throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)");
|
||||
if (this.checkIfEmptyOrNotString(this.envSettings["database.name"]))
|
||||
throw new Error("set valid value to DB_NAME (name of database or filepath for sqlite)");
|
||||
if (
|
||||
this.checkIfEmptyOrNotString(this.envSettings["database.host"]) &&
|
||||
this.envSettings["database.type"] != "sqlite"
|
||||
)
|
||||
throw new Error("set valid value to DB_HOST");
|
||||
if (
|
||||
this.checkIfEmptyOrNotString(this.envSettings["database.username"]) &&
|
||||
this.envSettings["database.type"] != "sqlite"
|
||||
)
|
||||
throw new Error("set valid value to DB_USERNAME");
|
||||
if (
|
||||
this.checkIfEmptyOrNotString(this.envSettings["database.password"]) &&
|
||||
this.envSettings["database.type"] != "sqlite"
|
||||
)
|
||||
throw new Error("set valid value to DB_PASSWORD");
|
||||
}
|
||||
|
||||
private static checkIfEmptyOrNotString(val: any) {
|
||||
return typeof val != "string" || val == "";
|
||||
}
|
||||
}
|
13
src/index.ts
13
src/index.ts
|
@ -1,8 +1,10 @@
|
|||
import "dotenv/config";
|
||||
import "./handlebars.config";
|
||||
import express from "express";
|
||||
import { SettingHelper } from "./helpers/settingsHelper";
|
||||
|
||||
import { BACKUP_AUTO_RESTORE, configCheck, SERVER_PORT } from "./env.defaults";
|
||||
SettingHelper.configurEnv();
|
||||
import { configCheck } from "./env.defaults";
|
||||
configCheck();
|
||||
|
||||
import { PermissionObject } from "./type/permissionTypes";
|
||||
|
@ -22,18 +24,21 @@ declare global {
|
|||
import { dataSource } from "./data-source";
|
||||
import BackupHelper from "./helpers/backupHelper";
|
||||
dataSource.initialize().then(async () => {
|
||||
if ((BACKUP_AUTO_RESTORE as "true" | "false") == "true" && (await dataSource.createQueryRunner().hasTable("user"))) {
|
||||
if (await dataSource.createQueryRunner().hasTable("user")) {
|
||||
await BackupHelper.autoRestoreBackup().catch((err) => {
|
||||
console.log(`${new Date().toISOString()}: failed auto-restoring database`, err);
|
||||
});
|
||||
}
|
||||
SettingHelper.configure();
|
||||
});
|
||||
|
||||
const app = express();
|
||||
import router from "./routes/index";
|
||||
router(app);
|
||||
app.listen(process.env.NODE_ENV ? SERVER_PORT : 5000, () => {
|
||||
console.log(`${new Date().toISOString()}: listening on port ${process.env.NODE_ENV ? SERVER_PORT : 5000}`);
|
||||
app.listen(process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000, () => {
|
||||
console.log(
|
||||
`${new Date().toISOString()}: listening on port ${process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000}`
|
||||
);
|
||||
});
|
||||
|
||||
import schedule from "node-schedule";
|
||||
|
|
|
@ -2,13 +2,16 @@ import { MigrationInterface, QueryRunner, Table } from "typeorm";
|
|||
import BackupHelper from "../helpers/backupHelper";
|
||||
import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "./ormHelper";
|
||||
import InternalException from "../exceptions/internalException";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
export class BackupAndResetDatabase1738166124200 implements MigrationInterface {
|
||||
name = "BackupAndResetDatabase1738166124200";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
let query = DB_TYPE == "postgres" ? "SELECT name FROM migrations" : "SELECT `name` FROM `migrations`";
|
||||
let query =
|
||||
SettingHelper.getEnvSetting("database.type") == "postgres"
|
||||
? "SELECT name FROM migrations"
|
||||
: "SELECT `name` FROM `migrations`";
|
||||
let migrations = await queryRunner.query(query);
|
||||
if (
|
||||
(await queryRunner.hasTable("user")) &&
|
||||
|
|
|
@ -54,7 +54,7 @@ import {
|
|||
newsletter_recipients_table,
|
||||
newsletter_table,
|
||||
} from "./baseSchemaTables/newsletter";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
export class CreateSchema1738166167472 implements MigrationInterface {
|
||||
name = "CreateSchema1738166167472";
|
||||
|
@ -84,6 +84,7 @@ export class CreateSchema1738166167472 implements MigrationInterface {
|
|||
await queryRunner.createTable(member_executive_positions_table, true, true, true);
|
||||
await queryRunner.createTable(member_qualifications_table, true, true, true);
|
||||
|
||||
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
|
||||
if (DB_TYPE == "postgres") await queryRunner.createView(member_view_postgres, true);
|
||||
else if (DB_TYPE == "mysql") await queryRunner.createView(member_view_mysql, true);
|
||||
else if (DB_TYPE == "sqlite") await queryRunner.createView(member_view_sqlite, true);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
export type ORMType = "int" | "bigint" | "boolean" | "date" | "datetime" | "time" | "text" | "varchar" | "uuid";
|
||||
export type ORMDefault = "currentTimestamp" | "string" | "boolean" | "number" | "null";
|
||||
export type ColumnConfig = {
|
||||
|
@ -13,7 +15,7 @@ export type Primary = {
|
|||
};
|
||||
|
||||
export function getTypeByORM(type: ORMType, nullable: boolean = false, length: number = 255): ColumnConfig {
|
||||
const dbType = process.env.DB_TYPE;
|
||||
const dbType = SettingHelper.getEnvSetting("database.type");
|
||||
|
||||
const typeMap: Record<string, Record<ORMType, string>> = {
|
||||
mysql: {
|
||||
|
@ -63,7 +65,7 @@ export function getTypeByORM(type: ORMType, nullable: boolean = false, length: n
|
|||
}
|
||||
|
||||
export function getDefaultByORM<T = string | null>(type: ORMDefault, data?: string | number | boolean): T {
|
||||
const dbType = process.env.DB_TYPE;
|
||||
const dbType = SettingHelper.getEnvSetting("database.type");
|
||||
|
||||
const typeMap: Record<string, Record<ORMDefault, string | null>> = {
|
||||
mysql: {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { membership } from "../../../entity/club/member/membership";
|
|||
import DatabaseActionException from "../../../exceptions/databaseActionException";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { memberView } from "../../../views/memberView";
|
||||
import { DB_TYPE } from "../../../env.defaults";
|
||||
import { SettingHelper } from "../../../helpers/settingsHelper";
|
||||
|
||||
export default abstract class MemberService {
|
||||
/**
|
||||
|
@ -169,7 +169,7 @@ export default abstract class MemberService {
|
|||
"member.firstMembershipEntry",
|
||||
"member.memberships",
|
||||
"membership_first",
|
||||
DB_TYPE == "postgres"
|
||||
SettingHelper.getEnvSetting("database.type") == "postgres"
|
||||
? 'membership_first.memberId = member.id AND membership_first.start = (SELECT MIN("m_first"."start") FROM "membership" "m_first" WHERE "m_first"."memberId" = "member"."id")'
|
||||
: "membership_first.memberId = member.id AND membership_first.start = (SELECT MIN(m_first.start) FROM membership m_first WHERE m_first.memberId = member.id)"
|
||||
)
|
||||
|
@ -177,7 +177,7 @@ export default abstract class MemberService {
|
|||
"member.lastMembershipEntry",
|
||||
"member.memberships",
|
||||
"membership_last",
|
||||
DB_TYPE == "postgres"
|
||||
SettingHelper.getEnvSetting("database.type") == "postgres"
|
||||
? 'membership_last.memberId = member.id AND membership_last.start = (SELECT MAX("m_last"."start") FROM "membership" "m_last" WHERE "m_last"."memberId" = "member"."id")'
|
||||
: "membership_last.memberId = member.id AND membership_last.start = (SELECT MAX(m_last.start) FROM membership m_last WHERE m_last.memberId = member.id)"
|
||||
)
|
||||
|
|
89
src/type/settingTypes.ts
Normal file
89
src/type/settingTypes.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import ms from "ms";
|
||||
import { StringHelper } from "../helpers/stringHelper";
|
||||
|
||||
export type SettingTopic = "club" | "app" | "session" | "mail" | "backup" | "security";
|
||||
|
||||
export type SettingString =
|
||||
| "club.name"
|
||||
| "club.imprint"
|
||||
| "club.privacy"
|
||||
| "club.website"
|
||||
| "app.custom_login_message"
|
||||
| "app.show_link_to_calendar"
|
||||
| "session.jwt_secret"
|
||||
| "session.jwt_expiration"
|
||||
| "session.refresh_expiration"
|
||||
| "session.pwa_refresh_expiration"
|
||||
| "mail.username"
|
||||
| "mail.password"
|
||||
| "mail.host"
|
||||
| "mail.port"
|
||||
| "mail.secure"
|
||||
| "backup.interval"
|
||||
| "backup.copies"
|
||||
| "security.strict_limit"
|
||||
| "security.strict_limit_window"
|
||||
| "security.strict_limit_request_count"
|
||||
| "security.limit"
|
||||
| "security.limit_window"
|
||||
| "security.limit_request_count"
|
||||
| "security.trust_proxy";
|
||||
|
||||
export type SettingTypeAtom = "longstring" | "string" | "ms" | "number" | "boolean" | "url";
|
||||
export type SettingType = SettingTypeAtom | `${SettingTypeAtom}/crypt` | `${SettingTypeAtom}/rand`;
|
||||
|
||||
export const settingsType: {
|
||||
[key in SettingString]: {
|
||||
type: SettingType | SettingType[];
|
||||
default?: string | number | boolean | ms.StringValue;
|
||||
optional?: boolean;
|
||||
};
|
||||
} = {
|
||||
"club.name": { type: "string", default: "FF Admin" },
|
||||
"club.imprint": { type: "url", optional: true },
|
||||
"club.privacy": { type: "url", optional: true },
|
||||
"club.website": { type: "url", optional: true },
|
||||
"app.custom_login_message": { type: "string", optional: true },
|
||||
"app.show_link_to_calendar": { type: "boolean", default: true },
|
||||
"session.jwt_secret": { type: "longstring/rand", default: StringHelper.random(64) },
|
||||
"session.jwt_expiration": { type: "ms", default: "15m" },
|
||||
"session.refresh_expiration": { type: "ms", default: "1d" },
|
||||
"session.pwa_refresh_expiration": { type: "ms", default: "5d" },
|
||||
"mail.username": { type: "string", optional: false },
|
||||
"mail.password": { type: "string/crypt", optional: false },
|
||||
"mail.host": { type: "url", optional: false },
|
||||
"mail.port": { type: "number", default: 587 },
|
||||
"mail.secure": { type: "boolean", default: false },
|
||||
"backup.interval": { type: "number", default: 1 },
|
||||
"backup.copies": { type: "number", default: 7 },
|
||||
"security.strict_limit": { type: "boolean", default: true },
|
||||
"security.strict_limit_window": { type: "ms", default: "15m" },
|
||||
"security.strict_limit_request_count": { type: "number", default: 15 },
|
||||
"security.limit": { type: "boolean", default: true },
|
||||
"security.limit_window": { type: "ms", default: "1m" },
|
||||
"security.limit_request_count": { type: "number", default: 500 },
|
||||
"security.trust_proxy": { type: ["boolean", "number"], optional: true },
|
||||
};
|
||||
|
||||
/** ENV Settings */
|
||||
export type EnvSettingString =
|
||||
| "database.type"
|
||||
| "database.host"
|
||||
| "database.port"
|
||||
| "database.name"
|
||||
| "database.username"
|
||||
| "database.password";
|
||||
|
||||
export const envSettingsType: {
|
||||
[key in EnvSettingString]: {
|
||||
type: SettingType | SettingType[];
|
||||
default?: string;
|
||||
};
|
||||
} = {
|
||||
"database.type": { type: "string", default: "postgres" },
|
||||
"database.host": { type: "string" },
|
||||
"database.port": { type: "string", default: "5432" },
|
||||
"database.name": { type: "string" },
|
||||
"database.username": { type: "string" },
|
||||
"database.password": { type: "string" },
|
||||
};
|
|
@ -1,10 +1,11 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
let durationInDays: string;
|
||||
let durationInYears: string;
|
||||
let exactDuration: string;
|
||||
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
|
||||
if (DB_TYPE == "postgres") {
|
||||
durationInDays = `SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start")`;
|
||||
durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")))`;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { memberQualifications } from "../entity/club/member/memberQualifications";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
let durationInDays: string;
|
||||
let durationInYears: string;
|
||||
let exactDuration: string;
|
||||
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
|
||||
if (DB_TYPE == "postgres") {
|
||||
durationInDays = `SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") `;
|
||||
durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")))`;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { member } from "../entity/club/member/member";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
let todayAge: string;
|
||||
let ageThisYear: string;
|
||||
let exactAge: string;
|
||||
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
|
||||
if (DB_TYPE == "postgres") {
|
||||
todayAge = `DATE_PART('year', AGE(CURRENT_DATE, member.birthdate))`;
|
||||
ageThisYear = `EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate)`;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { membership } from "../entity/club/member/membership";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { SettingHelper } from "../helpers/settingsHelper";
|
||||
|
||||
let durationInDays: string;
|
||||
let durationInYears: string;
|
||||
let exactDuration: string;
|
||||
const DB_TYPE = SettingHelper.getEnvSetting("database.type");
|
||||
if (DB_TYPE == "postgres") {
|
||||
durationInDays = `SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") `;
|
||||
durationInYears = `SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")))`;
|
||||
|
|
Loading…
Add table
Reference in a new issue