From 97ffae009b35537ce2cb688ff15183aff42d8cee Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 7 Jun 2025 15:20:20 +0200 Subject: [PATCH 1/5] migrate schema to postgres only --- src/data-source.ts | 38 +- src/entity/club/calendar.ts | 2 +- src/entity/club/member/member.ts | 7 +- src/entity/configuration/query.ts | 4 +- src/entity/management/user.ts | 4 +- src/env.defaults.ts | 4 +- .../admin/club/member/dateMappingHelper.ts | 11 +- src/migrations/1738166167472-CreateSchema.ts | 177 -------- .../1742549956787-templatesAndProtocolSort.ts | 55 --- src/migrations/1742922178643-queryToUUID.ts | 94 ---- .../1744351418751-newsletterColumnType.ts | 47 -- .../1744795756230-QueryUpdatedAt.ts | 22 - .../1745059495807-settingsFromEnv.ts | 16 - .../1745059495808-settingsFromEnv_set.ts | 29 -- .../1746006549262-memberCreatedAt.ts | 21 - .../1746252454922-UserLoginRoutine.ts | 39 -- .../1748509435932-addDateToNewsletter.ts | 21 - .../1748607842929-addMembershipTotalView.ts | 21 - .../1748953828644-memberExtendData.ts | 34 -- ...> 1749296262915-BackupAndResetDatabase.ts} | 16 +- src/migrations/1749296280721-CreateSchema.ts | 177 ++++++++ src/migrations/baseSchemaTables/admin.ts | 38 +- src/migrations/baseSchemaTables/calendar.ts | 9 +- src/migrations/baseSchemaTables/member.ts | 405 ++---------------- src/migrations/baseSchemaTables/newsletter.ts | 14 +- src/migrations/baseSchemaTables/protocol.ts | 7 +- .../baseSchemaTables/query_template.ts | 10 +- src/migrations/ormHelper.ts | 85 +--- src/service/club/member/memberService.ts | 9 +- src/views/memberExecutivePositionView.ts | 46 +- src/views/memberQualificationsView.ts | 46 +- src/views/memberView.ts | 40 +- src/views/membershipsView.ts | 53 +-- 33 files changed, 363 insertions(+), 1238 deletions(-) delete mode 100644 src/migrations/1738166167472-CreateSchema.ts delete mode 100644 src/migrations/1742549956787-templatesAndProtocolSort.ts delete mode 100644 src/migrations/1742922178643-queryToUUID.ts delete mode 100644 src/migrations/1744351418751-newsletterColumnType.ts delete mode 100644 src/migrations/1744795756230-QueryUpdatedAt.ts delete mode 100644 src/migrations/1745059495807-settingsFromEnv.ts delete mode 100644 src/migrations/1745059495808-settingsFromEnv_set.ts delete mode 100644 src/migrations/1746006549262-memberCreatedAt.ts delete mode 100644 src/migrations/1746252454922-UserLoginRoutine.ts delete mode 100644 src/migrations/1748509435932-addDateToNewsletter.ts delete mode 100644 src/migrations/1748607842929-addMembershipTotalView.ts delete mode 100644 src/migrations/1748953828644-memberExtendData.ts rename src/migrations/{1738166124200-BackupAndResetDatabase.ts => 1749296262915-BackupAndResetDatabase.ts} (76%) create mode 100644 src/migrations/1749296280721-CreateSchema.ts diff --git a/src/data-source.ts b/src/data-source.ts index 7f8a9e0..ed56dad 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import "reflect-metadata"; import { DataSource } from "typeorm"; -import { configCheck, DB_HOST, DB_NAME, DB_PASSWORD, DB_PORT, DB_TYPE, DB_USERNAME } from "./env.defaults"; +import { configCheck, DB_HOST, DB_NAME, DB_PASSWORD, DB_PORT, DB_USERNAME } from "./env.defaults"; import { user } from "./entity/management/user"; import { refresh } from "./entity/refresh"; @@ -45,27 +45,16 @@ import { webapi } from "./entity/management/webapi"; import { webapiPermission } from "./entity/management/webapi_permission"; import { salutation } from "./entity/configuration/salutation"; import { setting } from "./entity/management/setting"; - -import { BackupAndResetDatabase1738166124200 } from "./migrations/1738166124200-BackupAndResetDatabase"; -import { CreateSchema1738166167472 } from "./migrations/1738166167472-CreateSchema"; -import { TemplatesAndProtocolSort1742549956787 } from "./migrations/1742549956787-templatesAndProtocolSort"; -import { QueryToUUID1742922178643 } from "./migrations/1742922178643-queryToUUID"; -import { NewsletterColumnType1744351418751 } from "./migrations/1744351418751-newsletterColumnType"; -import { QueryUpdatedAt1744795756230 } from "./migrations/1744795756230-QueryUpdatedAt"; -import { SettingsFromEnv1745059495807 } from "./migrations/1745059495807-settingsFromEnv"; -import { MemberCreatedAt1746006549262 } from "./migrations/1746006549262-memberCreatedAt"; -import { UserLoginRoutine1746252454922 } from "./migrations/1746252454922-UserLoginRoutine"; -import { SettingsFromEnv_SET1745059495808 } from "./migrations/1745059495808-settingsFromEnv_set"; -import { AddDateToNewsletter1748509435932 } from "./migrations/1748509435932-addDateToNewsletter"; -import { AddMembershipTotalView1748607842929 } from "./migrations/1748607842929-addMembershipTotalView"; import { education } from "./entity/configuration/education"; import { memberEducations } from "./entity/club/member/memberEducations"; -import { MemberExtendData1748953828644 } from "./migrations/1748953828644-memberExtendData"; + +import { BackupAndResetDatabase1749296262915 } from "./migrations/1749296262915-BackupAndResetDatabase"; +import { CreateSchema1749296280721 } from "./migrations/1749296280721-CreateSchema"; configCheck(); const dataSource = new DataSource({ - type: DB_TYPE as any, + type: "postgres", host: DB_HOST, port: DB_PORT, username: DB_USERNAME, @@ -73,7 +62,6 @@ const dataSource = new DataSource({ database: DB_NAME, synchronize: false, logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"], - bigNumberStrings: false, entities: [ user, refresh, @@ -120,21 +108,7 @@ const dataSource = new DataSource({ webapiPermission, setting, ], - migrations: [ - BackupAndResetDatabase1738166124200, - CreateSchema1738166167472, - TemplatesAndProtocolSort1742549956787, - QueryToUUID1742922178643, - NewsletterColumnType1744351418751, - QueryUpdatedAt1744795756230, - SettingsFromEnv1745059495807, - SettingsFromEnv_SET1745059495808, - MemberCreatedAt1746006549262, - UserLoginRoutine1746252454922, - AddDateToNewsletter1748509435932, - AddMembershipTotalView1748607842929, - MemberExtendData1748953828644, - ], + migrations: [BackupAndResetDatabase1749296262915, CreateSchema1749296280721], migrationsRun: true, migrationsTransactionMode: "each", subscribers: [], diff --git a/src/entity/club/calendar.ts b/src/entity/club/calendar.ts index 6e64553..a647e61 100644 --- a/src/entity/club/calendar.ts +++ b/src/entity/club/calendar.ts @@ -45,7 +45,7 @@ export class calendar { @UpdateDateColumn() updatedAt: Date; - @Column({ type: "varchar", nullable: true, default: null, unique: true }) + @Column({ type: "varchar", length: "255", nullable: true, default: null, unique: true }) webpageId: string; @ManyToOne(() => calendarType, (t) => t.calendar, { diff --git a/src/entity/club/member/member.ts b/src/entity/club/member/member.ts index 5f349c3..57d8bb6 100644 --- a/src/entity/club/member/member.ts +++ b/src/entity/club/member/member.ts @@ -8,6 +8,7 @@ import { OneToMany, OneToOne, PrimaryColumn, + PrimaryGeneratedColumn, } from "typeorm"; import { membership } from "./membership"; import { memberAwards } from "./memberAwards"; @@ -20,7 +21,7 @@ import { memberEducations } from "./memberEducations"; @Entity() export class member { - @PrimaryColumn({ generated: "uuid", type: "varchar" }) + @PrimaryGeneratedColumn("uuid") id: string; @Column({ type: "varchar", length: 255 }) @@ -38,8 +39,8 @@ export class member { @Column({ type: "varchar", length: 255, unique: true, nullable: true }) internalId?: string; - @Column({ type: "varchar", length: 255, nullable: true }) - note?: string; + @Column({ type: "varchar", length: 255 }) + note: string; @Column() salutationId: number; diff --git a/src/entity/configuration/query.ts b/src/entity/configuration/query.ts index 68f95be..419ad43 100644 --- a/src/entity/configuration/query.ts +++ b/src/entity/configuration/query.ts @@ -1,8 +1,8 @@ -import { Column, Entity, PrimaryColumn, UpdateDateColumn } from "typeorm"; +import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; @Entity() export class query { - @PrimaryColumn({ generated: "uuid", type: "varchar" }) + @PrimaryGeneratedColumn("uuid") id: string; @Column({ type: "varchar", length: 255, unique: true }) diff --git a/src/entity/management/user.ts b/src/entity/management/user.ts index d659acb..27cd06a 100644 --- a/src/entity/management/user.ts +++ b/src/entity/management/user.ts @@ -1,4 +1,4 @@ -import { Column, Entity, JoinTable, ManyToMany, OneToMany, PrimaryColumn } from "typeorm"; +import { Column, Entity, JoinTable, ManyToMany, OneToMany, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { role } from "./role"; import { userPermission } from "./user_permission"; import { LoginRoutineEnum } from "../../enums/loginRoutineEnum"; @@ -7,7 +7,7 @@ import { APPLICATION_SECRET } from "../../env.defaults"; @Entity() export class user { - @PrimaryColumn({ generated: "uuid", type: "varchar" }) + @PrimaryGeneratedColumn("uuid") id: string; @Column({ type: "varchar", unique: true, length: 255 }) diff --git a/src/env.defaults.ts b/src/env.defaults.ts index c6df8ae..7a408d6 100644 --- a/src/env.defaults.ts +++ b/src/env.defaults.ts @@ -2,9 +2,8 @@ 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_PORT = Number(process.env.DB_PORT ?? 5432); export const DB_NAME = process.env.DB_NAME ?? ""; export const DB_USERNAME = process.env.DB_USERNAME ?? ""; export const DB_PASSWORD = process.env.DB_PASSWORD ?? ""; @@ -39,7 +38,6 @@ export const TRUST_PROXY = ((): Array | string | boolean | number | null })(); export function configCheck() { - if (DB_TYPE != "mysql" && DB_TYPE != "postgres") throw new Error("set valid value to DB_TYPE (mysql|postgres)"); if (DB_HOST == "" || typeof DB_HOST != "string") 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") throw new Error("set valid value to DB_USERNAME"); diff --git a/src/factory/admin/club/member/dateMappingHelper.ts b/src/factory/admin/club/member/dateMappingHelper.ts index 8fdd072..40bab62 100644 --- a/src/factory/admin/club/member/dateMappingHelper.ts +++ b/src/factory/admin/club/member/dateMappingHelper.ts @@ -1,14 +1,5 @@ -import { DB_TYPE } from "../../../../env.defaults"; - export default abstract class DateMappingHelper { static mapDate(entry: any) { - switch (DB_TYPE) { - case "postgres": - return `${entry?.years ?? 0} years ${entry?.months ?? 0} months ${entry?.days ?? 0} days`; - case "mysql": - return entry.toString(); - case "sqlite": - return entry; - } + return `${entry?.years ?? 0} years ${entry?.months ?? 0} months ${entry?.days ?? 0} days`; } } diff --git a/src/migrations/1738166167472-CreateSchema.ts b/src/migrations/1738166167472-CreateSchema.ts deleted file mode 100644 index df9c6fd..0000000 --- a/src/migrations/1738166167472-CreateSchema.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { - invite_table, - refresh_table, - reset_table, - role_permission_table, - role_table, - user_permission_table, - user_roles_table, - user_table, - webapi_permission_table, - webapi_table, -} from "./baseSchemaTables/admin"; -import { templateUsage } from "../entity/configuration/templateUsage"; -import { - award_table, - communication_type_table, - executive_position_table, - member_awards_table, - member_communication_table, - member_executive_positions_table, - member_executive_positions_view_mysql, - member_executive_positions_view_postgres, - member_executive_positions_view_sqlite, - member_qualifications_table, - member_qualifications_view_mysql, - member_qualifications_view_postgres, - member_qualifications_view_sqlite, - member_table, - member_view_mysql, - member_view_postgres, - member_view_sqlite, - membership_status_table, - membership_table, - membership_view_mysql, - membership_view_postgres, - membership_view_sqlite, - qualification_table, - salutation_table, -} from "./baseSchemaTables/member"; -import { query_table, template_table, template_usage_table } from "./baseSchemaTables/query_template"; -import { - protocol_agenda_table, - protocol_decision_table, - protocol_presence_table, - protocol_printout_table, - protocol_table, - protocol_voting_table, -} from "./baseSchemaTables/protocol"; -import { calendar_table, calendar_type_table } from "./baseSchemaTables/calendar"; -import { - newsletter_config_table, - newsletter_dates_table, - newsletter_recipients_table, - newsletter_table, -} from "./baseSchemaTables/newsletter"; -import { DB_TYPE } from "../env.defaults"; - -export class CreateSchema1738166167472 implements MigrationInterface { - name = "CreateSchema1738166167472"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.createTable(reset_table, true, true, true); - await queryRunner.createTable(invite_table, true, true, true); - await queryRunner.createTable(role_table, true, true, true); - await queryRunner.createTable(role_permission_table, true, true, true); - await queryRunner.createTable(user_table, true, true, true); - await queryRunner.createTable(user_roles_table, true, true, true); - await queryRunner.createTable(user_permission_table, true, true, true); - await queryRunner.createTable(refresh_table, true, true, true); - await queryRunner.createTable(webapi_table, true, true, true); - await queryRunner.createTable(webapi_permission_table, true, true, true); - - await queryRunner.createTable(salutation_table, true, true, true); - await queryRunner.createTable(award_table, true, true, true); - await queryRunner.createTable(communication_type_table, true, true, true); - await queryRunner.createTable(membership_status_table, true, true, true); - await queryRunner.createTable(executive_position_table, true, true, true); - await queryRunner.createTable(qualification_table, true, true, true); - await queryRunner.createTable(member_table, true, true, true); - await queryRunner.createTable(member_awards_table, true, true, true); - await queryRunner.createTable(member_communication_table, true, true, true); - await queryRunner.createTable(membership_table, true, true, true); - await queryRunner.createTable(member_executive_positions_table, true, true, true); - await queryRunner.createTable(member_qualifications_table, true, true, true); - - 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); - if (DB_TYPE == "postgres") await queryRunner.createView(membership_view_postgres, true); - else if (DB_TYPE == "mysql") await queryRunner.createView(membership_view_mysql, true); - else if (DB_TYPE == "sqlite") await queryRunner.createView(membership_view_sqlite, true); - if (DB_TYPE == "postgres") await queryRunner.createView(member_qualifications_view_postgres, true); - else if (DB_TYPE == "mysql") await queryRunner.createView(member_qualifications_view_mysql, true); - else if (DB_TYPE == "sqlite") await queryRunner.createView(member_qualifications_view_sqlite, true); - if (DB_TYPE == "postgres") await queryRunner.createView(member_executive_positions_view_postgres, true); - else if (DB_TYPE == "mysql") await queryRunner.createView(member_executive_positions_view_mysql, true); - else if (DB_TYPE == "sqlite") await queryRunner.createView(member_executive_positions_view_sqlite, true); - - await queryRunner.createTable(query_table, true, true, true); - await queryRunner.createTable(template_table, true, true, true); - await queryRunner.createTable(template_usage_table, true, true, true); - - await queryRunner.manager - .createQueryBuilder() - .insert() - .into(templateUsage) - .values([{ scope: "newsletter" }, { scope: "protocol" }, { scope: "member.list" }]) - .orIgnore() - .execute(); - - await queryRunner.createTable(protocol_table, true, true, true); - await queryRunner.createTable(protocol_agenda_table, true, true, true); - await queryRunner.createTable(protocol_decision_table, true, true, true); - await queryRunner.createTable(protocol_presence_table, true, true, true); - await queryRunner.createTable(protocol_voting_table, true, true, true); - await queryRunner.createTable(protocol_printout_table, true, true, true); - - await queryRunner.createTable(calendar_type_table, true, true, true); - await queryRunner.createTable(calendar_table, true, true, true); - - await queryRunner.createTable(newsletter_config_table, true, true, true); - await queryRunner.createTable(newsletter_table, true, true, true); - await queryRunner.createTable(newsletter_dates_table, true, true, true); - await queryRunner.createTable(newsletter_recipients_table, true, true, true); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropTable("newsletter_dates", true, true, true); - await queryRunner.dropTable("newsletter_recipients", true, true, true); - await queryRunner.dropTable("newsletter", true, true, true); - await queryRunner.dropTable("newsletter_config", true, true, true); - - await queryRunner.dropTable("calendar", true, true, true); - await queryRunner.dropTable("calendar_type", true, true, true); - - await queryRunner.dropTable("protocol_agenda", true, true, true); - await queryRunner.dropTable("protocol_decision", true, true, true); - await queryRunner.dropTable("protocol_presence", true, true, true); - await queryRunner.dropTable("protocol_voting", true, true, true); - await queryRunner.dropTable("protocol_printout", true, true, true); - await queryRunner.dropTable("protocol", true, true, true); - - await queryRunner.dropTable("template_usage", true, true, true); - await queryRunner.dropTable("template", true, true, true); - await queryRunner.dropTable("query", true, true, true); - - await queryRunner.dropView("member_view"); - await queryRunner.dropView("membership_view"); - await queryRunner.dropView("member_qualifications_view"); - await queryRunner.dropView("member_executive_positions_view"); - - await queryRunner.dropTable("member_awards", true, true, true); - await queryRunner.dropTable("communication", true, true, true); - await queryRunner.dropTable("membership", true, true, true); - await queryRunner.dropTable("member_executive_positions", true, true, true); - await queryRunner.dropTable("member_qualifications", true, true, true); - await queryRunner.dropTable("member", true, true, true); - await queryRunner.dropTable("salutation", true, true, true); - await queryRunner.dropTable("award", true, true, true); - await queryRunner.dropTable("communication_type", true, true, true); - await queryRunner.dropTable("membership_status", true, true, true); - await queryRunner.dropTable("executive_position", true, true, true); - await queryRunner.dropTable("qualification", true, true, true); - - await queryRunner.dropTable("webapi_permission", true, true, true); - await queryRunner.dropTable("webapi", true, true, true); - await queryRunner.dropTable("refresh", true, true, true); - await queryRunner.dropTable("user_permission", true, true, true); - await queryRunner.dropTable("user_roles", true, true, true); - await queryRunner.dropTable("user", true, true, true); - await queryRunner.dropTable("role_permission", true, true, true); - await queryRunner.dropTable("role", true, true, true); - await queryRunner.dropTable("invite", true, true, true); - await queryRunner.dropTable("reset", true, true, true); - } -} diff --git a/src/migrations/1742549956787-templatesAndProtocolSort.ts b/src/migrations/1742549956787-templatesAndProtocolSort.ts deleted file mode 100644 index cc86bf8..0000000 --- a/src/migrations/1742549956787-templatesAndProtocolSort.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { templateUsage } from "../entity/configuration/templateUsage"; -import { getTypeByORM, getDefaultByORM } from "./ormHelper"; - -export class TemplatesAndProtocolSort1742549956787 implements MigrationInterface { - name = "TemplatesAndProtocolSort1742549956787"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.manager - .createQueryBuilder() - .insert() - .into(templateUsage) - .values([{ scope: "member" }]) - .orIgnore() - .execute(); - - await queryRunner.manager - .createQueryBuilder() - .delete() - .from(templateUsage) - .where({ scope: "member.list" }) - .execute(); - - await queryRunner.addColumn( - "protocol_agenda", - new TableColumn({ name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }) - ); - - await queryRunner.addColumn( - "protocol_decision", - new TableColumn({ name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }) - ); - - await queryRunner.addColumn( - "protocol_voting", - new TableColumn({ name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }) - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn("protocol_agenda", "sort"); - await queryRunner.dropColumn("protocol_decision", "sort"); - await queryRunner.dropColumn("protocol_voting", "sort"); - - await queryRunner.manager - .createQueryBuilder() - .insert() - .into(templateUsage) - .values([{ scope: "member.list" }]) - .orIgnore() - .execute(); - - await queryRunner.manager.createQueryBuilder().delete().from(templateUsage).where({ scope: "member" }).execute(); - } -} diff --git a/src/migrations/1742922178643-queryToUUID.ts b/src/migrations/1742922178643-queryToUUID.ts deleted file mode 100644 index 3902fb9..0000000 --- a/src/migrations/1742922178643-queryToUUID.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn, TableForeignKey } from "typeorm"; -import { getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "./ormHelper"; -import { query } from "../entity/configuration/query"; - -export class QueryToUUID1742922178643 implements MigrationInterface { - name = "QueryToUUID1742922178643"; - - public async up(queryRunner: QueryRunner): Promise { - const table = await queryRunner.getTable("newsletter"); - const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("recipientsByQueryId") !== -1); - await queryRunner.dropForeignKey("newsletter", foreignKey); - - // const entries = await queryRunner.manager.getRepository("query").find({ select: { title: true, query: true } }); - // await queryRunner.clearTable("query"); - - await queryRunner.dropColumn("newsletter", "recipientsByQueryId"); - await queryRunner.dropColumn("query", "id"); - - await queryRunner.addColumn( - "query", - new TableColumn({ - name: "id", - ...getTypeByORM("uuid"), - ...isUUIDPrimary, - }) - ); - await queryRunner.addColumn( - "newsletter", - new TableColumn({ - name: "recipientsByQueryId", - ...getTypeByORM("uuid", true), - }) - ); - - // await queryRunner.manager.getRepository("query").save(entries); - - await queryRunner.createForeignKey( - "newsletter", - new TableForeignKey({ - columnNames: ["recipientsByQueryId"], - referencedColumnNames: ["id"], - referencedTableName: "query", - onDelete: "CASCADE", - onUpdate: "RESTRICT", - }) - ); - } - - public async down(queryRunner: QueryRunner): Promise { - const table = await queryRunner.getTable("newsletter"); - const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("recipientsByQueryId") !== -1); - await queryRunner.dropForeignKey("newsletter", foreignKey); - - const entries = await queryRunner.manager.getRepository(query).find({ select: { title: true, query: true } }); - await queryRunner.clearTable("query"); - - await queryRunner.dropColumn("newsletter", "recipientsByQueryId"); - await queryRunner.dropColumn("query", "id"); - - await queryRunner.addColumn( - "query", - new TableColumn({ - name: "id", - ...getTypeByORM("int"), - ...isIncrementPrimary, - }) - ); - await queryRunner.addColumn( - "newsletter", - new TableColumn({ - name: "recipientsByQueryId", - ...getTypeByORM("int", true), - }) - ); - - await queryRunner.manager - .createQueryBuilder() - .insert() - .into("query") - .values(entries.map((e, i) => ({ ...e, id: i + 1 }))) - .execute(); - - await queryRunner.createForeignKey( - "newsletter", - new TableForeignKey({ - columnNames: ["recipientsByQueryId"], - referencedColumnNames: ["id"], - referencedTableName: "query", - onDelete: "CASCADE", - onUpdate: "RESTRICT", - }) - ); - } -} diff --git a/src/migrations/1744351418751-newsletterColumnType.ts b/src/migrations/1744351418751-newsletterColumnType.ts deleted file mode 100644 index 686869e..0000000 --- a/src/migrations/1744351418751-newsletterColumnType.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { getDefaultByORM, getTypeByORM } from "./ormHelper"; -import { newsletter } from "../entity/club/newsletter/newsletter"; - -export class NewsletterColumnType1744351418751 implements MigrationInterface { - name = "NewsletterColumnType1744351418751"; - - public async up(queryRunner: QueryRunner): Promise { - let newsletters = await queryRunner.manager - .getRepository("newsletter") - .find({ select: { id: true, newsletterTitle: true, newsletterSignatur: true } }); - - await queryRunner.dropColumn("newsletter", "newsletterTitle"); - await queryRunner.dropColumn("newsletter", "newsletterSignatur"); - - await queryRunner.addColumn( - "newsletter", - new TableColumn({ name: "newsletterTitle", ...getTypeByORM("text"), default: getDefaultByORM("string") }) - ); - await queryRunner.addColumn( - "newsletter", - new TableColumn({ name: "newsletterSignatur", ...getTypeByORM("text"), default: getDefaultByORM("string") }) - ); - - await queryRunner.manager.getRepository("newsletter").save(newsletters); - } - - public async down(queryRunner: QueryRunner): Promise { - let newsletters = await queryRunner.manager - .getRepository("newsletter") - .find({ select: { id: true, newsletterTitle: true, newsletterSignatur: true } }); - - await queryRunner.dropColumn("newsletter", "newsletterTitle"); - await queryRunner.dropColumn("newsletter", "newsletterSignatur"); - - await queryRunner.addColumn( - "newsletter", - new TableColumn({ name: "newsletterTitle", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }) - ); - await queryRunner.addColumn( - "newsletter", - new TableColumn({ name: "newsletterSignatur", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }) - ); - - await queryRunner.manager.getRepository("newsletter").save(newsletters); - } -} diff --git a/src/migrations/1744795756230-QueryUpdatedAt.ts b/src/migrations/1744795756230-QueryUpdatedAt.ts deleted file mode 100644 index 428ba0c..0000000 --- a/src/migrations/1744795756230-QueryUpdatedAt.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { getTypeByORM, getDefaultByORM } from "./ormHelper"; - -export class QueryUpdatedAt1744795756230 implements MigrationInterface { - name = "QueryUpdatedAt1744795756230"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumn( - "query", - new TableColumn({ - name: "updatedAt", - ...getTypeByORM("datetime", false, 6), - default: getDefaultByORM("currentTimestamp", 6), - onUpdate: getDefaultByORM("currentTimestamp", 6), - }) - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn("query", "updatedAt"); - } -} diff --git a/src/migrations/1745059495807-settingsFromEnv.ts b/src/migrations/1745059495807-settingsFromEnv.ts deleted file mode 100644 index 1af7e08..0000000 --- a/src/migrations/1745059495807-settingsFromEnv.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { setting_table } from "./baseSchemaTables/admin"; -import SettingHelper from "../helpers/settingsHelper"; -import ms from "ms"; - -export class SettingsFromEnv1745059495807 implements MigrationInterface { - name = "SettingsFromEnv1745059495807"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.createTable(setting_table, true, true, true); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropTable(setting_table.name, true, true, true); - } -} diff --git a/src/migrations/1745059495808-settingsFromEnv_set.ts b/src/migrations/1745059495808-settingsFromEnv_set.ts deleted file mode 100644 index 3a5729b..0000000 --- a/src/migrations/1745059495808-settingsFromEnv_set.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { setting_table } from "./baseSchemaTables/admin"; -import SettingHelper from "../helpers/settingsHelper"; -import ms from "ms"; - -export class SettingsFromEnv_SET1745059495808 implements MigrationInterface { - name = "SettingsFromEnv_SET1745059495808"; - - public async up(queryRunner: QueryRunner): Promise { - // transfer settings of env to database - await SettingHelper.setSetting("club.name", process.env.CLUB_NAME); - await SettingHelper.setSetting("club.website", process.env.CLUB_WEBSITE); - await SettingHelper.setSetting("session.jwt_expiration", process.env.JWT_EXPIRATION as ms.StringValue); - await SettingHelper.setSetting("session.refresh_expiration", process.env.REFRESH_EXPIRATION as ms.StringValue); - await SettingHelper.setSetting( - "session.pwa_refresh_expiration", - process.env.PWA_REFRESH_EXPIRATION as ms.StringValue - ); - await SettingHelper.setSetting("mail.username", process.env.MAIL_USERNAME); - await SettingHelper.setSetting("mail.password", process.env.MAIL_PASSWORD); - await SettingHelper.setSetting("mail.host", process.env.MAIL_HOST); - await SettingHelper.setSetting("mail.port", Number(process.env.MAIL_PORT ?? "578")); - await SettingHelper.setSetting("mail.secure", process.env.MAIL_SECURE == "true"); - await SettingHelper.setSetting("backup.interval", Number(process.env.BACKUP_INTERVAL ?? "1")); - await SettingHelper.setSetting("backup.copies", Number(process.env.BACKUP_COPIES ?? "7")); - } - - public async down(queryRunner: QueryRunner): Promise {} -} diff --git a/src/migrations/1746006549262-memberCreatedAt.ts b/src/migrations/1746006549262-memberCreatedAt.ts deleted file mode 100644 index 08f7669..0000000 --- a/src/migrations/1746006549262-memberCreatedAt.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { getTypeByORM, getDefaultByORM } from "./ormHelper"; - -export class MemberCreatedAt1746006549262 implements MigrationInterface { - name = "MemberCreatedAt1746006549262"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumn( - "member", - new TableColumn({ - name: "createdAt", - ...getTypeByORM("datetime", false, 6), - default: getDefaultByORM("currentTimestamp", 6), - }) - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn("member", "createdAt"); - } -} diff --git a/src/migrations/1746252454922-UserLoginRoutine.ts b/src/migrations/1746252454922-UserLoginRoutine.ts deleted file mode 100644 index b11f9b0..0000000 --- a/src/migrations/1746252454922-UserLoginRoutine.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { getDefaultByORM, getTypeByORM } from "./ormHelper"; -import { LoginRoutineEnum } from "../enums/loginRoutineEnum"; -import { CodingHelper } from "../helpers/codingHelper"; -import { APPLICATION_SECRET } from "../env.defaults"; - -export class UserLoginRoutine1746252454922 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - let users = await queryRunner.manager.getRepository("user").find({ select: ["id", "secret"] }); - - await queryRunner.dropColumns("user", ["secret", "static"]); - - await queryRunner.addColumns("user", [ - new TableColumn({ name: "secret", ...getTypeByORM("text"), default: getDefaultByORM("string") }), - new TableColumn({ - name: "routine", - ...getTypeByORM("varchar"), - default: getDefaultByORM("string", LoginRoutineEnum.totp), - }), - ]); - - await queryRunner.manager.getRepository("user").save(users.map((u) => ({ id: u.id, secret: u.secret }))); - } - - public async down(queryRunner: QueryRunner): Promise { - let users = await queryRunner.manager.getRepository("user").find({ select: ["id", "secret"] }); - - await queryRunner.dropColumn("user", "secret"); - - await queryRunner.addColumns("user", [ - new TableColumn({ name: "secret", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }), - new TableColumn({ name: "static", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }), - ]); - - await queryRunner.manager.getRepository("user").save(users.map((u) => ({ id: u.id, secret: u.secret }))); - - await queryRunner.dropColumn("user", "routine"); - } -} diff --git a/src/migrations/1748509435932-addDateToNewsletter.ts b/src/migrations/1748509435932-addDateToNewsletter.ts deleted file mode 100644 index 5f4b8fa..0000000 --- a/src/migrations/1748509435932-addDateToNewsletter.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { getTypeByORM, getDefaultByORM } from "./ormHelper"; - -export class AddDateToNewsletter1748509435932 implements MigrationInterface { - name = "AddDateToNewsletter1748509435932"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.addColumn( - "newsletter", - new TableColumn({ - name: "createdAt", - ...getTypeByORM("datetime", false, 6), - default: getDefaultByORM("currentTimestamp", 6), - }) - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn("newsletter", "createdAt"); - } -} diff --git a/src/migrations/1748607842929-addMembershipTotalView.ts b/src/migrations/1748607842929-addMembershipTotalView.ts deleted file mode 100644 index 97cfea0..0000000 --- a/src/migrations/1748607842929-addMembershipTotalView.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { DB_TYPE } from "../env.defaults"; -import { - membership_total_view_mysql, - membership_total_view_postgres, - membership_total_view_sqlite, -} from "./baseSchemaTables/member"; - -export class AddMembershipTotalView1748607842929 implements MigrationInterface { - name = "AddMembershipTotalView1748607842929"; - - public async up(queryRunner: QueryRunner): Promise { - if (DB_TYPE == "postgres") await queryRunner.createView(membership_total_view_postgres, true); - else if (DB_TYPE == "mysql") await queryRunner.createView(membership_total_view_mysql, true); - else if (DB_TYPE == "sqlite") await queryRunner.createView(membership_total_view_sqlite, true); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropView("membership_total_view"); - } -} diff --git a/src/migrations/1748953828644-memberExtendData.ts b/src/migrations/1748953828644-memberExtendData.ts deleted file mode 100644 index a2ccb44..0000000 --- a/src/migrations/1748953828644-memberExtendData.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; -import { - education_table, - member_educations_table, - member_view2_mysql, - member_view2_postgres, - member_view2_sqlite, -} from "./baseSchemaTables/member"; -import { getDefaultByORM, getTypeByORM } from "./ormHelper"; -import { DB_TYPE } from "../env.defaults"; - -export class MemberExtendData1748953828644 implements MigrationInterface { - name = "MemberExtendData1748953828644"; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.createTable(education_table, true, true, true); - await queryRunner.createTable(member_educations_table, true, true, true); - await queryRunner.addColumn( - "member", - new TableColumn({ name: "note", ...getTypeByORM("varchar", true), default: getDefaultByORM("null") }) - ); - - await queryRunner.dropView("member_view"); - if (DB_TYPE == "postgres") await queryRunner.createView(member_view2_postgres, true); - else if (DB_TYPE == "mysql") await queryRunner.createView(member_view2_mysql, true); - else if (DB_TYPE == "sqlite") await queryRunner.createView(member_view2_sqlite, true); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropTable(member_educations_table, true, true, true); - await queryRunner.dropTable(education_table, true, true, true); - await queryRunner.dropColumn("member", "note"); - } -} diff --git a/src/migrations/1738166124200-BackupAndResetDatabase.ts b/src/migrations/1749296262915-BackupAndResetDatabase.ts similarity index 76% rename from src/migrations/1738166124200-BackupAndResetDatabase.ts rename to src/migrations/1749296262915-BackupAndResetDatabase.ts index f0656ba..8280d8c 100644 --- a/src/migrations/1738166124200-BackupAndResetDatabase.ts +++ b/src/migrations/1749296262915-BackupAndResetDatabase.ts @@ -1,21 +1,19 @@ 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 BackupHelper from "../helpers/backupHelper"; +import { getTypeByORM, isIncrementPrimary, getDefaultByORM } from "./ormHelper"; -export class BackupAndResetDatabase1738166124200 implements MigrationInterface { - name = "BackupAndResetDatabase1738166124200"; +export class BackupAndResetDatabase1749296262915 implements MigrationInterface { + name = "BackupAndResetDatabase1749296262915"; public async up(queryRunner: QueryRunner): Promise { - let query = DB_TYPE == "postgres" ? "SELECT name FROM migrations" : "SELECT `name` FROM `migrations`"; - let migrations = await queryRunner.query(query); + let migrations = await queryRunner.query("SELECT name FROM migrations"); if ( (await queryRunner.hasTable("user")) && - migrations.findIndex((m: any) => m.name == "MoveSendNewsletterFlag1737816852011") == -1 + migrations.findIndex((m: any) => m.name == "MemberExtendData1748953828644") == -1 ) { throw new InternalException( - "Cannot update due to skiped version. Update to v1.2.2 Version first to prevent data loss and get access to the newer Versions." + "Cannot update due to skiped version. Update to v1.6.0 Version first to prevent data loss and get access to the newer Versions." ); } diff --git a/src/migrations/1749296280721-CreateSchema.ts b/src/migrations/1749296280721-CreateSchema.ts new file mode 100644 index 0000000..168810a --- /dev/null +++ b/src/migrations/1749296280721-CreateSchema.ts @@ -0,0 +1,177 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; +import { + reset_table, + invite_table, + role_table, + role_permission_table, + user_table, + user_roles_table, + user_permission_table, + refresh_table, + webapi_table, + webapi_permission_table, + setting_table, +} from "./baseSchemaTables/admin"; +import { calendar_type_table, calendar_table } from "./baseSchemaTables/calendar"; +import { + salutation_table, + award_table, + communication_type_table, + membership_status_table, + executive_position_table, + qualification_table, + member_table, + member_awards_table, + member_communication_table, + membership_table, + member_executive_positions_table, + member_qualifications_table, + member_view, + membership_view, + member_qualifications_view, + member_executive_positions_view, + education_table, + member_educations_table, + membership_total_view, +} from "./baseSchemaTables/member"; +import { + newsletter_config_table, + newsletter_table, + newsletter_dates_table, + newsletter_recipients_table, +} from "./baseSchemaTables/newsletter"; +import { + protocol_table, + protocol_agenda_table, + protocol_decision_table, + protocol_presence_table, + protocol_voting_table, + protocol_printout_table, +} from "./baseSchemaTables/protocol"; +import { query_table, template_table, template_usage_table } from "./baseSchemaTables/query_template"; + +export class CreateSchema1749296280721 implements MigrationInterface { + name = "CreateSchema1749296280721"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable(reset_table, true, true, true); + await queryRunner.createTable(invite_table, true, true, true); + await queryRunner.createTable(role_table, true, true, true); + await queryRunner.createTable(role_permission_table, true, true, true); + await queryRunner.createTable(user_table, true, true, true); + await queryRunner.createTable(user_roles_table, true, true, true); + await queryRunner.createTable(user_permission_table, true, true, true); + await queryRunner.createTable(refresh_table, true, true, true); + await queryRunner.createTable(webapi_table, true, true, true); + await queryRunner.createTable(webapi_permission_table, true, true, true); + await queryRunner.createTable(setting_table, true, true, true); + + await queryRunner.createTable(salutation_table, true, true, true); + await queryRunner.createTable(award_table, true, true, true); + await queryRunner.createTable(communication_type_table, true, true, true); + await queryRunner.createTable(membership_status_table, true, true, true); + await queryRunner.createTable(executive_position_table, true, true, true); + await queryRunner.createTable(qualification_table, true, true, true); + await queryRunner.createTable(education_table, true, true, true); + await queryRunner.createTable(member_table, true, true, true); + await queryRunner.createTable(member_awards_table, true, true, true); + await queryRunner.createTable(member_communication_table, true, true, true); + await queryRunner.createTable(membership_table, true, true, true); + await queryRunner.createTable(member_executive_positions_table, true, true, true); + await queryRunner.createTable(member_qualifications_table, true, true, true); + await queryRunner.createTable(member_educations_table, true, true, true); + + await queryRunner.createView(member_view, true); + await queryRunner.createView(membership_view, true); + await queryRunner.createView(membership_total_view, true); + await queryRunner.createView(member_qualifications_view, true); + await queryRunner.createView(member_executive_positions_view, true); + + await queryRunner.createTable(query_table, true, true, true); + await queryRunner.createTable(template_table, true, true, true); + await queryRunner.createTable(template_usage_table, true, true, true); + + await queryRunner.manager + .createQueryBuilder() + .insert() + .into(template_usage_table.name) + .values([ + { scope: "newsletter" }, + { scope: "protocol" }, + { scope: "member" }, + { scope: "listprint" }, + { scope: "listprint.member" }, + ]) + .orIgnore() + .execute(); + + await queryRunner.createTable(protocol_table, true, true, true); + await queryRunner.createTable(protocol_agenda_table, true, true, true); + await queryRunner.createTable(protocol_decision_table, true, true, true); + await queryRunner.createTable(protocol_presence_table, true, true, true); + await queryRunner.createTable(protocol_voting_table, true, true, true); + await queryRunner.createTable(protocol_printout_table, true, true, true); + + await queryRunner.createTable(calendar_type_table, true, true, true); + await queryRunner.createTable(calendar_table, true, true, true); + + await queryRunner.createTable(newsletter_config_table, true, true, true); + await queryRunner.createTable(newsletter_table, true, true, true); + await queryRunner.createTable(newsletter_dates_table, true, true, true); + await queryRunner.createTable(newsletter_recipients_table, true, true, true); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable(newsletter_dates_table, true, true, true); + await queryRunner.dropTable(newsletter_recipients_table, true, true, true); + await queryRunner.dropTable(newsletter_table, true, true, true); + await queryRunner.dropTable(newsletter_config_table, true, true, true); + + await queryRunner.dropTable(calendar_table, true, true, true); + await queryRunner.dropTable(calendar_type_table, true, true, true); + + await queryRunner.dropTable(protocol_agenda_table, true, true, true); + await queryRunner.dropTable(protocol_decision_table, true, true, true); + await queryRunner.dropTable(protocol_presence_table, true, true, true); + await queryRunner.dropTable(protocol_voting_table, true, true, true); + await queryRunner.dropTable(protocol_printout_table, true, true, true); + await queryRunner.dropTable(protocol_table, true, true, true); + + await queryRunner.dropTable(template_usage_table, true, true, true); + await queryRunner.dropTable(template_table, true, true, true); + await queryRunner.dropTable(query_table, true, true, true); + + await queryRunner.dropView(member_view); + await queryRunner.dropView(membership_view); + await queryRunner.dropView(membership_total_view); + await queryRunner.dropView(member_qualifications_view); + await queryRunner.dropView(member_executive_positions_view); + + await queryRunner.dropTable(member_awards_table, true, true, true); + await queryRunner.dropTable(member_communication_table, true, true, true); + await queryRunner.dropTable(membership_table, true, true, true); + await queryRunner.dropTable(member_executive_positions_table, true, true, true); + await queryRunner.dropTable(member_qualifications_table, true, true, true); + await queryRunner.dropTable(member_educations_table, true, true, true); + await queryRunner.dropTable(member_table, true, true, true); + await queryRunner.dropTable(salutation_table, true, true, true); + await queryRunner.dropTable(award_table, true, true, true); + await queryRunner.dropTable(communication_type_table, true, true, true); + await queryRunner.dropTable(membership_status_table, true, true, true); + await queryRunner.dropTable(executive_position_table, true, true, true); + await queryRunner.dropTable(qualification_table, true, true, true); + await queryRunner.dropTable(education_table, true, true, true); + + await queryRunner.dropTable(setting_table, true, true, true); + await queryRunner.dropTable(webapi_permission_table, true, true, true); + await queryRunner.dropTable(webapi_table, true, true, true); + await queryRunner.dropTable(refresh_table, true, true, true); + await queryRunner.dropTable(user_permission_table, true, true, true); + await queryRunner.dropTable(user_roles_table, true, true, true); + await queryRunner.dropTable(user_table, true, true, true); + await queryRunner.dropTable(role_permission_table, true, true, true); + await queryRunner.dropTable(role_table, true, true, true); + await queryRunner.dropTable(invite_table, true, true, true); + await queryRunner.dropTable(reset_table, true, true, true); + } +} diff --git a/src/migrations/baseSchemaTables/admin.ts b/src/migrations/baseSchemaTables/admin.ts index 6ece9ad..b898aba 100644 --- a/src/migrations/baseSchemaTables/admin.ts +++ b/src/migrations/baseSchemaTables/admin.ts @@ -1,5 +1,6 @@ -import { Table, TableForeignKey } from "typeorm"; +import { Table, TableForeignKey, TableIndex, TableUnique } from "typeorm"; import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; +import { LoginRoutineEnum } from "../../enums/loginRoutineEnum"; export const invite_table = new Table({ name: "invite", @@ -16,7 +17,12 @@ export const role_table = new Table({ name: "role", columns: [ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, - { name: "role", ...getTypeByORM("varchar"), isUnique: true }, + { name: "role", ...getTypeByORM("varchar") }, + ], + uniques: [ + new TableUnique({ + columnNames: ["role"], + }), ], }); @@ -45,8 +51,8 @@ export const user_table = new Table({ { name: "username", ...getTypeByORM("varchar"), isUnique: true }, { name: "firstname", ...getTypeByORM("varchar") }, { name: "lastname", ...getTypeByORM("varchar") }, - { name: "secret", ...getTypeByORM("varchar") }, - { name: "static", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "secret", ...getTypeByORM("text") }, + { name: "routine", ...getTypeByORM("varchar"), default: getDefaultByORM("string", LoginRoutineEnum.totp) }, { name: "isOwner", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, ], }); @@ -73,6 +79,14 @@ export const user_roles_table = new Table({ onUpdate: "RESTRICT", }), ], + indices: [ + new TableIndex({ + columnNames: ["userId"], + }), + new TableIndex({ + columnNames: ["roleId"], + }), + ], }); export const user_permission_table = new Table({ @@ -114,11 +128,19 @@ export const webapi_table = new Table({ name: "webapi", columns: [ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, - { name: "token", ...getTypeByORM("varchar"), isUnique: true }, - { name: "title", ...getTypeByORM("varchar"), isUnique: true }, + { name: "token", ...getTypeByORM("text") }, + { name: "title", ...getTypeByORM("varchar") }, { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, - { name: "lastUsage", ...getTypeByORM("datetime", true, 6), default: getDefaultByORM("null") }, - { name: "expiry", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { name: "lastUsage", ...getTypeByORM("datetime", true, 6) }, + { name: "expiry", ...getTypeByORM("date", true) }, + ], + uniques: [ + new TableUnique({ + columnNames: ["token"], + }), + new TableUnique({ + columnNames: ["title"], + }), ], }); diff --git a/src/migrations/baseSchemaTables/calendar.ts b/src/migrations/baseSchemaTables/calendar.ts index 155dc46..8d6e758 100644 --- a/src/migrations/baseSchemaTables/calendar.ts +++ b/src/migrations/baseSchemaTables/calendar.ts @@ -1,4 +1,4 @@ -import { Table, TableForeignKey } from "typeorm"; +import { Table, TableForeignKey, TableUnique } from "typeorm"; import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; export const calendar_type_table = new Table({ @@ -32,7 +32,7 @@ export const calendar_table = new Table({ default: getDefaultByORM("currentTimestamp", 6), onUpdate: getDefaultByORM("currentTimestamp", 6), }, - { name: "webpageId", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "webpageId", ...getTypeByORM("varchar", true) }, { name: "typeId", ...getTypeByORM("int") }, ], foreignKeys: [ @@ -44,4 +44,9 @@ export const calendar_table = new Table({ onUpdate: "RESTRICT", }), ], + uniques: [ + new TableUnique({ + columnNames: ["webpageId"], + }), + ], }); diff --git a/src/migrations/baseSchemaTables/member.ts b/src/migrations/baseSchemaTables/member.ts index 663da51..26d02a5 100644 --- a/src/migrations/baseSchemaTables/member.ts +++ b/src/migrations/baseSchemaTables/member.ts @@ -1,4 +1,4 @@ -import { Table, TableForeignKey, View } from "typeorm"; +import { Table, TableForeignKey, TableUnique, View } from "typeorm"; import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; export const salutation_table = new Table({ @@ -66,11 +66,13 @@ export const member_table = new Table({ columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "salutationId", ...getTypeByORM("int") }, - { name: "internalId", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "internalId", ...getTypeByORM("varchar", true) }, { name: "firstname", ...getTypeByORM("varchar") }, { name: "lastname", ...getTypeByORM("varchar") }, { name: "nameaffix", ...getTypeByORM("varchar") }, { name: "birthdate", ...getTypeByORM("date") }, + { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, + { name: "note", ...getTypeByORM("varchar") }, ], foreignKeys: [ new TableForeignKey({ @@ -81,6 +83,11 @@ export const member_table = new Table({ onUpdate: "RESTRICT", }), ], + uniques: [ + new TableUnique({ + columnNames: ["internalId"], + }), + ], }); export const membership_table = new Table({ @@ -172,7 +179,7 @@ export const member_awards_table = new Table({ name: "member_awards", columns: [ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, - { name: "given", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "given", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", true) }, { name: "note", ...getTypeByORM("varchar"), isNullable: true }, { name: "date", ...getTypeByORM("date") }, { name: "memberId", ...getTypeByORM("uuid") }, @@ -203,13 +210,13 @@ export const member_communication_table = new Table({ { name: "preferred", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, { name: "isSendNewsletter", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, { name: "isSMSAlarming", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, - { name: "mobile", ...getTypeByORM("varchar"), isNullable: true }, - { name: "email", ...getTypeByORM("varchar"), isNullable: true }, - { name: "postalCode", ...getTypeByORM("varchar"), default: getDefaultByORM("null"), isNullable: true }, - { name: "city", ...getTypeByORM("varchar"), isNullable: true }, - { name: "street", ...getTypeByORM("varchar"), isNullable: true }, + { name: "mobile", ...getTypeByORM("varchar", true) }, + { name: "email", ...getTypeByORM("varchar", true) }, + { name: "postalCode", ...getTypeByORM("varchar", true) }, + { name: "city", ...getTypeByORM("varchar", true) }, + { name: "street", ...getTypeByORM("varchar", true) }, { name: "streetNumber", ...getTypeByORM("int", true) }, - { name: "streetNumberAddition", ...getTypeByORM("varchar"), isNullable: true }, + { name: "streetNumberAddition", ...getTypeByORM("varchar", true) }, { name: "memberId", ...getTypeByORM("uuid") }, { name: "typeId", ...getTypeByORM("int") }, ], @@ -261,180 +268,30 @@ export const member_educations_table = new Table({ }); /** views */ -export const member_view_mysql = new View({ - name: "member_view", - expression: ` - SELECT - \`member\`.\`id\` AS \`id\`, - \`member\`.\`internalId\` AS \`internalId\`, - \`member\`.\`firstname\` AS \`firstname\`, - \`member\`.\`lastname\` AS \`lastname\`, - \`member\`.\`nameaffix\` AS \`nameaffix\`, - \`member\`.\`birthdate\` AS \`birthdate\`, - \`salutation\`.\`salutation\` AS \`salutation\`, - TIMESTAMPDIFF(YEAR, \`member\`.\`birthdate\`, CURDATE()) AS \`todayAge\`, - YEAR(CURDATE()) - YEAR(\`member\`.\`birthdate\`) AS \`ageThisYear\`, - CONCAT( - TIMESTAMPDIFF(YEAR, \`member\`.\`birthdate\`, CURDATE()), ' years ', - TIMESTAMPDIFF(MONTH, \`member\`.\`birthdate\`, CURDATE()) % 12, ' months ', - TIMESTAMPDIFF(DAY, - DATE_ADD( - \`member\`.\`birthdate\`, - INTERVAL TIMESTAMPDIFF(MONTH, \`member\`.\`birthdate\`, CURDATE()) MONTH - ), - CURDATE() - ), ' days' - ) AS \`exactAge\` - FROM \`member\` \`member\` - LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - `, -}); -export const member_view_postgres = new View({ +export const member_view = new View({ name: "member_view", expression: ` SELECT "member"."id" AS "id", - "member"."internalId" AS "internalId", "member"."firstname" AS "firstname", "member"."lastname" AS "lastname", "member"."nameaffix" AS "nameaffix", "member"."birthdate" AS "birthdate", - "salutation"."salutation" AS "salutation", - DATE_PART('year', AGE(CURRENT_DATE, member.birthdate)) AS "todayAge", - EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate) AS "ageThisYear", - AGE(CURRENT_DATE, member.birthdate) AS "exactAge" - FROM "member" "member" - LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" - `, -}); - -export const member_view_sqlite = new View({ - name: "member_view", - expression: ` - SELECT - member.id AS id, - member.internalId AS internalId, - member.firstname AS firstname, - member.lastname AS lastname, - member.nameaffix AS nameaffix, - member.birthdate AS birthdate, - salutation.salutation AS salutation, - (strftime('%Y', 'now') - strftime('%Y', member.birthdate) - (strftime('%m-%d', 'now') < strftime('%m-%d', member.birthdate))) AS todayAge, - FLOOR(strftime('%Y', 'now') - strftime('%Y', member.birthdate)) AS ageThisYear, - (strftime('%Y', 'now') - strftime('%Y', member.birthdate)) || ' years ' || - (strftime('%m', 'now') - strftime('%m', member.birthdate)) || ' months ' || - (strftime('%d', 'now') - strftime('%d', member.birthdate)) || ' days' - AS exactAge - FROM member member - LEFT JOIN salutation salutation ON salutation.id=member.salutationId - `, -}); - -export const member_view2_mysql = new View({ - name: "member_view", - expression: ` - SELECT - \`member\`.\`id\` AS \`id\`, - \`member\`.\`internalId\` AS \`internalId\`, - \`member\`.\`note\` AS \`note\`, - \`member\`.\`firstname\` AS \`firstname\`, - \`member\`.\`lastname\` AS \`lastname\`, - \`member\`.\`nameaffix\` AS \`nameaffix\`, - \`member\`.\`birthdate\` AS \`birthdate\`, - \`salutation\`.\`salutation\` AS \`salutation\`, - TIMESTAMPDIFF(YEAR, \`member\`.\`birthdate\`, CURDATE()) AS \`todayAge\`, - YEAR(CURDATE()) - YEAR(\`member\`.\`birthdate\`) AS \`ageThisYear\`, - CONCAT( - TIMESTAMPDIFF(YEAR, \`member\`.\`birthdate\`, CURDATE()), ' years ', - TIMESTAMPDIFF(MONTH, \`member\`.\`birthdate\`, CURDATE()) % 12, ' months ', - TIMESTAMPDIFF(DAY, - DATE_ADD( - \`member\`.\`birthdate\`, - INTERVAL TIMESTAMPDIFF(MONTH, \`member\`.\`birthdate\`, CURDATE()) MONTH - ), - CURDATE() - ), ' days' - ) AS \`exactAge\` - FROM \`member\` \`member\` - LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - `, -}); - -export const member_view2_postgres = new View({ - name: "member_view", - expression: ` - SELECT - "member"."id" AS "id", "member"."internalId" AS "internalId", "member"."note" AS "note", - "member"."firstname" AS "firstname", - "member"."lastname" AS "lastname", - "member"."nameaffix" AS "nameaffix", - "member"."birthdate" AS "birthdate", "salutation"."salutation" AS "salutation", - DATE_PART('year', AGE(CURRENT_DATE, member.birthdate)) AS "todayAge", - EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate) AS "ageThisYear", - AGE(CURRENT_DATE, member.birthdate) AS "exactAge" + DATE_PART('year', AGE(CURRENT_DATE, "member"."birthdate")) AS "todayAge", + EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM "member"."birthdate") AS "ageThisYear", + AGE(CURRENT_DATE, "member"."birthdate") AS "exactAge" FROM "member" "member" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" - `, + ` + .replace(/\s+/g, " ") + .trim(), }); -export const member_view2_sqlite = new View({ - name: "member_view", - expression: ` - SELECT - member.id AS id, - member.internalId AS internalId, - member.note AS note, - member.firstname AS firstname, - member.lastname AS lastname, - member.nameaffix AS nameaffix, - member.birthdate AS birthdate, - salutation.salutation AS salutation, - (strftime('%Y', 'now') - strftime('%Y', member.birthdate) - (strftime('%m-%d', 'now') < strftime('%m-%d', member.birthdate))) AS todayAge, - FLOOR(strftime('%Y', 'now') - strftime('%Y', member.birthdate)) AS ageThisYear, - (strftime('%Y', 'now') - strftime('%Y', member.birthdate)) || ' years ' || - (strftime('%m', 'now') - strftime('%m', member.birthdate)) || ' months ' || - (strftime('%d', 'now') - strftime('%d', member.birthdate)) || ' days' - AS exactAge - FROM member member - LEFT JOIN salutation salutation ON salutation.id=member.salutationId - `, -}); - -export const member_executive_positions_view_mysql = new View({ - name: "member_executive_positions_view", - expression: ` - SELECT - \`executivePosition\`.\`id\` AS \`positionId\`, - \`executivePosition\`.\`position\` AS \`position\`, - \`member\`.\`id\` AS \`memberId\`, - \`member\`.\`firstname\` AS \`memberFirstname\`, - \`member\`.\`lastname\` AS \`memberLastname\`, - \`member\`.\`nameaffix\` AS \`memberNameaffix\`, - \`member\`.\`birthdate\` AS \`memberBirthdate\`, - \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(DATEDIFF(COALESCE(\`memberExecutivePositions\`.\`end\`, CURDATE()), \`memberExecutivePositions\`.\`start\`)) AS \`durationInDays\`, - SUM(TIMESTAMPDIFF(YEAR, \`memberExecutivePositions\`.\`start\`, COALESCE(\`memberExecutivePositions\`.\`end\`, CURDATE()))) AS \`durationInYears\`, - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, \`memberExecutivePositions\`.\`start\`, COALESCE(\`memberExecutivePositions\`.\`end\`, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, \`memberExecutivePositions\`.\`start\`, COALESCE(\`memberExecutivePositions\`.\`end\`, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, \`memberExecutivePositions\`.\`start\`, COALESCE(\`memberExecutivePositions\`.\`end\`, CURDATE())), 30))), - ' days' - ) AS \`exactDuration\` - FROM \`member_executive_positions\` \`memberExecutivePositions\` - LEFT JOIN \`executive_position\` \`executivePosition\` ON \`executivePosition\`.\`id\`=\`memberExecutivePositions\`.\`executivePositionId\` - LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`memberExecutivePositions\`.\`memberId\` - LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`executivePosition\`.\`id\`, \`member\`.\`id\`, \`salutation\`.\`id\` - `, -}); - -export const member_executive_positions_view_postgres = new View({ +export const member_executive_positions_view = new View({ name: "member_executive_positions_view", expression: ` SELECT @@ -454,66 +311,12 @@ export const member_executive_positions_view_postgres = new View({ LEFT JOIN "member" "member" ON "member"."id"="memberExecutivePositions"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "executivePosition"."id", "member"."id", "salutation"."id" - `, + ` + .replace(/\s+/g, " ") + .trim(), }); -export const member_executive_positions_view_sqlite = new View({ - name: "member_executive_positions_view", - expression: ` - SELECT - executivePosition.id AS positionId, - executivePosition.position AS position, - member.id AS memberId, - member.firstname AS memberFirstname, - member.lastname AS memberLastname, - member.nameaffix AS memberNameaffix, - member.birthdate AS memberBirthdate, - salutation.salutation AS memberSalutation, - SUM(JULIANDAY(COALESCE(memberExecutivePositions.end, DATE('now'))) - JULIANDAY(memberExecutivePositions.start)) AS durationInDays, - SUM(FLOOR((JULIANDAY(COALESCE(memberExecutivePositions.end, DATE('now'))) - JULIANDAY(memberExecutivePositions.start)) / 365.25)) AS durationInYears, - SUM((strftime('%Y', COALESCE(memberExecutivePositions.end, DATE('now'))) - strftime('%Y', memberExecutivePositions.start))) || ' years ' || - SUM((strftime('%m', COALESCE(memberExecutivePositions.end, DATE('now'))) - strftime('%m', memberExecutivePositions.start))) || ' months ' || - SUM((strftime('%d', COALESCE(memberExecutivePositions.end, DATE('now'))) - strftime('%d', memberExecutivePositions.start))) || ' days' - AS exactDuration - FROM member_executive_positions memberExecutivePositions - LEFT JOIN executive_position executivePosition ON executivePosition.id=memberExecutivePositions.executivePositionId - LEFT JOIN member member ON member.id=memberExecutivePositions.memberId - LEFT JOIN salutation salutation ON salutation.id=member.salutationId - GROUP BY executivePosition.id, member.id, salutation.id - `, -}); - -export const member_qualifications_view_mysql = new View({ - name: "member_qualifications_view", - expression: ` - SELECT - \`qualification\`.\`id\` AS \`qualificationId\`, - \`qualification\`.\`qualification\` AS \`qualification\`, - \`member\`.\`id\` AS \`memberId\`, - \`member\`.\`firstname\` AS \`memberFirstname\`, - \`member\`.\`lastname\` AS \`memberLastname\`, - \`member\`.\`nameaffix\` AS \`memberNameaffix\`, - \`member\`.\`birthdate\` AS \`memberBirthdate\`, - \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(DATEDIFF(COALESCE(\`memberQualifications\`.\`end\`, CURDATE()), \`memberQualifications\`.\`start\`)) AS \`durationInDays\`, - SUM(TIMESTAMPDIFF(YEAR, \`memberQualifications\`.\`start\`, COALESCE(\`memberQualifications\`.\`end\`, CURDATE()))) AS \`durationInYears\`, - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, \`memberQualifications\`.\`start\`, COALESCE(\`memberQualifications\`.\`end\`, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, \`memberQualifications\`.\`start\`, COALESCE(\`memberQualifications\`.\`end\`, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, \`memberQualifications\`.\`start\`, COALESCE(\`memberQualifications\`.\`end\`, CURDATE())), 30))), - ' days' - ) AS \`exactDuration\` - FROM \`member_qualifications\` \`memberQualifications\` - LEFT JOIN \`qualification\` \`qualification\` ON \`qualification\`.\`id\`=\`memberQualifications\`.\`qualificationId\` - LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`memberQualifications\`.\`memberId\` - LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`qualification\`.\`id\`, \`member\`.\`id\`, \`salutation\`.\`id\` - `, -}); - -export const member_qualifications_view_postgres = new View({ +export const member_qualifications_view = new View({ name: "member_qualifications_view", expression: ` SELECT @@ -533,66 +336,12 @@ export const member_qualifications_view_postgres = new View({ LEFT JOIN "member" "member" ON "member"."id"="memberQualifications"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "qualification"."id", "member"."id", "salutation"."id" - `, + ` + .replace(/\s+/g, " ") + .trim(), }); -export const member_qualifications_view_sqlite = new View({ - name: "member_qualifications_view", - expression: ` - SELECT - qualification.id AS qualificationId, - qualification.qualification AS qualification, - member.id AS memberId, - member.firstname AS memberFirstname, - member.lastname AS memberLastname, - member.nameaffix AS memberNameaffix, - member.birthdate AS memberBirthdate, - salutation.salutation AS memberSalutation, - SUM(JULIANDAY(COALESCE(memberQualifications.end, DATE('now'))) - JULIANDAY(memberQualifications.start)) AS durationInDays, - SUM(FLOOR((JULIANDAY(COALESCE(memberQualifications.end, DATE('now'))) - JULIANDAY(memberQualifications.start)) / 365.25)) AS durationInYears, - SUM((strftime('%Y', COALESCE(memberQualifications.end, DATE('now'))) - strftime('%Y', memberQualifications.start))) || ' years ' || - SUM((strftime('%m', COALESCE(memberQualifications.end, DATE('now'))) - strftime('%m', memberQualifications.start))) || ' months ' || - SUM((strftime('%d', COALESCE(memberQualifications.end, DATE('now'))) - strftime('%d', memberQualifications.start))) || ' days' - AS exactDuration - FROM member_qualifications memberQualifications - LEFT JOIN qualification qualification ON qualification.id=memberQualifications.qualificationId - LEFT JOIN member member ON member.id=memberQualifications.memberId - LEFT JOIN salutation salutation ON salutation.id=member.salutationId - GROUP BY qualification.id, member.id, salutation.id - `, -}); - -export const membership_view_mysql = new View({ - name: "membership_view", - expression: ` - SELECT - \`status\`.\`id\` AS \`statusId\`, - \`status\`.\`status\` AS \`status\`, - \`member\`.\`id\` AS \`memberId\`, - \`member\`.\`firstname\` AS \`memberFirstname\`, - \`member\`.\`lastname\` AS \`memberLastname\`, - \`member\`.\`nameaffix\` AS \`memberNameaffix\`, - \`member\`.\`birthdate\` AS \`memberBirthdate\`, - \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(DATEDIFF(COALESCE(\`membership\`.\`end\`, CURDATE()), \`membership\`.\`start\`)) AS \`durationInDays\`, - SUM(TIMESTAMPDIFF(YEAR, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE()))) AS \`durationInYears\`, - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE())), 30))), - ' days' - ) AS \`exactDuration\` - FROM \`membership\` \`membership\` - LEFT JOIN \`membership_status\` \`status\` ON \`status\`.\`id\`=\`membership\`.\`statusId\` - LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`membership\`.\`memberId\` - LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`status\`.\`id\`, \`member\`.\`id\`, \`salutation\`.\`id\` - `, -}); - -export const membership_view_postgres = new View({ +export const membership_view = new View({ name: "membership_view", expression: ` SELECT @@ -611,65 +360,13 @@ export const membership_view_postgres = new View({ LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" - GROUP BY "status"."id","member"."id", "salutation"."id" - `, + GROUP BY "status"."id", "member"."id", "salutation"."id" + ` + .replace(/\s+/g, " ") + .trim(), }); -export const membership_view_sqlite = new View({ - name: "membership_view", - expression: ` - SELECT - status.id AS statusId, - status.status AS status, - member.id AS memberId, - member.firstname AS memberFirstname, - member.lastname AS memberLastname, - member.nameaffix AS memberNameaffix, - member.birthdate AS memberBirthdate, - salutation.salutation AS memberSalutation, - SUM(JULIANDAY(COALESCE(membership.end, DATE('now'))) - JULIANDAY(membership.start)) AS durationInDays, - SUM(FLOOR((JULIANDAY(COALESCE(membership.end, DATE('now'))) - JULIANDAY(membership.start)) / 365.25)) AS durationInYears, - SUM((strftime('%Y', COALESCE(membership.end, DATE('now'))) - strftime('%Y', membership.start))) || ' years ' || - SUM((strftime('%m', COALESCE(membership.end, DATE('now'))) - strftime('%m', membership.start))) || ' months ' || - SUM((strftime('%d', COALESCE(membership.end, DATE('now'))) - strftime('%d', membership.start))) || ' days' - AS exactDuration - FROM membership membership - LEFT JOIN membership_status status ON status.id=membership.statusId - LEFT JOIN member member ON member.id=membership.memberId - LEFT JOIN salutation salutation ON salutation.id=member.salutationId - GROUP BY status.id, member.id, salutation.id - `, -}); - -export const membership_total_view_mysql = new View({ - name: "membership_total_view", - expression: ` - SELECT - \`member\`.\`id\` AS \`memberId\`, - \`member\`.\`firstname\` AS \`memberFirstname\`, - \`member\`.\`lastname\` AS \`memberLastname\`, - \`member\`.\`nameaffix\` AS \`memberNameaffix\`, - \`member\`.\`birthdate\` AS \`memberBirthdate\`, - \`salutation\`.\`salutation\` AS \`memberSalutation\`, - SUM(DATEDIFF(COALESCE(\`membership\`.\`end\`, CURDATE()), \`membership\`.\`start\`)) AS \`durationInDays\`, - SUM(TIMESTAMPDIFF(YEAR, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE()))) AS \`durationInYears\`, - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, \`membership\`.\`start\`, COALESCE(\`membership\`.\`end\`, CURDATE())), 30))), - ' days' - ) AS \`exactDuration\` - FROM \`membership\` \`membership\` - LEFT JOIN \`membership_status\` \`status\` ON \`status\`.\`id\`=\`membership\`.\`statusId\` - LEFT JOIN \`member\` \`member\` ON \`member\`.\`id\`=\`membership\`.\`memberId\` - LEFT JOIN \`salutation\` \`salutation\` ON \`salutation\`.\`id\`=\`member\`.\`salutationId\` - GROUP BY \`member\`.\`id\`, \`salutation\`.\`id\` - `, -}); - -export const membership_total_view_postgres = new View({ +export const membership_total_view = new View({ name: "membership_total_view", expression: ` SELECT @@ -687,29 +384,7 @@ export const membership_total_view_postgres = new View({ LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "member"."id", "salutation"."id" - `, -}); - -export const membership_total_view_sqlite = new View({ - name: "membership_total_view", - expression: ` - SELECT - member.id AS memberId, - member.firstname AS memberFirstname, - member.lastname AS memberLastname, - member.nameaffix AS memberNameaffix, - member.birthdate AS memberBirthdate, - salutation.salutation AS memberSalutation, - SUM(JULIANDAY(COALESCE(membership.end, DATE('now'))) - JULIANDAY(membership.start)) AS durationInDays, - SUM(FLOOR((JULIANDAY(COALESCE(membership.end, DATE('now'))) - JULIANDAY(membership.start)) / 365.25)) AS durationInYears, - SUM((strftime('%Y', COALESCE(membership.end, DATE('now'))) - strftime('%Y', membership.start))) || ' years ' || - SUM((strftime('%m', COALESCE(membership.end, DATE('now'))) - strftime('%m', membership.start))) || ' months ' || - SUM((strftime('%d', COALESCE(membership.end, DATE('now'))) - strftime('%d', membership.start))) || ' days' - AS exactDuration - FROM membership membership - LEFT JOIN membership_status status ON status.id=membership.statusId - LEFT JOIN member member ON member.id=membership.memberId - LEFT JOIN salutation salutation ON salutation.id=member.salutationId - GROUP BY member.id, salutation.id - `, + ` + .replace(/\s+/g, " ") + .trim(), }); diff --git a/src/migrations/baseSchemaTables/newsletter.ts b/src/migrations/baseSchemaTables/newsletter.ts index 537428f..2141cc7 100644 --- a/src/migrations/baseSchemaTables/newsletter.ts +++ b/src/migrations/baseSchemaTables/newsletter.ts @@ -1,4 +1,4 @@ -import { Table, TableForeignKey } from "typeorm"; +import { Table, TableForeignKey, TableUnique } from "typeorm"; import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "../ormHelper"; export const newsletter_table = new Table({ @@ -7,11 +7,12 @@ export const newsletter_table = new Table({ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, { name: "title", ...getTypeByORM("varchar") }, { name: "description", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, - { name: "newsletterTitle", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, + { name: "newsletterTitle", ...getTypeByORM("text"), default: getDefaultByORM("string") }, { name: "newsletterText", ...getTypeByORM("text"), default: getDefaultByORM("string") }, - { name: "newsletterSignatur", ...getTypeByORM("varchar"), default: getDefaultByORM("string") }, + { name: "newsletterSignatur", ...getTypeByORM("text"), default: getDefaultByORM("string") }, { name: "isSent", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, - { name: "recipientsByQueryId", ...getTypeByORM("int", true) }, + { name: "recipientsByQueryId", ...getTypeByORM("uuid", true) }, + { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, ], foreignKeys: [ new TableForeignKey({ @@ -22,6 +23,11 @@ export const newsletter_table = new Table({ onUpdate: "RESTRICT", }), ], + uniques: [ + new TableUnique({ + columnNames: ["title"], + }), + ], }); export const newsletter_dates_table = new Table({ diff --git a/src/migrations/baseSchemaTables/protocol.ts b/src/migrations/baseSchemaTables/protocol.ts index fd1cc89..c04fca3 100644 --- a/src/migrations/baseSchemaTables/protocol.ts +++ b/src/migrations/baseSchemaTables/protocol.ts @@ -1,11 +1,11 @@ -import { Table, TableForeignKey } from "typeorm"; +import { Table, TableForeignKey, TableUnique } from "typeorm"; import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "../ormHelper"; export const protocol_table = new Table({ name: "protocol", columns: [ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, - { name: "title", ...getTypeByORM("varchar") }, + { name: "title", ...getTypeByORM("varchar"), isUnique: true }, { name: "date", ...getTypeByORM("date") }, { name: "starttime", ...getTypeByORM("time", true) }, { name: "endtime", ...getTypeByORM("time", true) }, @@ -19,6 +19,7 @@ export const protocol_agenda_table = new Table({ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, { name: "topic", ...getTypeByORM("varchar") }, { name: "context", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ @@ -38,6 +39,7 @@ export const protocol_decision_table = new Table({ { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, { name: "topic", ...getTypeByORM("varchar") }, { name: "context", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ @@ -86,6 +88,7 @@ export const protocol_voting_table = new Table({ { name: "favour", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "abstain", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "against", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, + { name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "protocolId", ...getTypeByORM("int") }, ], foreignKeys: [ diff --git a/src/migrations/baseSchemaTables/query_template.ts b/src/migrations/baseSchemaTables/query_template.ts index da4eb44..2d8c4c8 100644 --- a/src/migrations/baseSchemaTables/query_template.ts +++ b/src/migrations/baseSchemaTables/query_template.ts @@ -1,12 +1,18 @@ import { Table, TableForeignKey } from "typeorm"; -import { getDefaultByORM, getTypeByORM, isIncrementPrimary } from "../ormHelper"; +import { getDefaultByORM, getTypeByORM, isIncrementPrimary, isUUIDPrimary } from "../ormHelper"; export const query_table = new Table({ name: "query", columns: [ - { name: "id", ...getTypeByORM("int"), ...isIncrementPrimary }, + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "title", ...getTypeByORM("varchar"), isUnique: true }, { name: "query", ...getTypeByORM("text"), default: getDefaultByORM("string") }, + { + name: "updatedAt", + ...getTypeByORM("datetime", false, 6), + default: getDefaultByORM("currentTimestamp", 6), + onUpdate: getDefaultByORM("currentTimestamp", 6), + }, ], }); diff --git a/src/migrations/ormHelper.ts b/src/migrations/ormHelper.ts index 8ebe5c9..c376f2b 100644 --- a/src/migrations/ormHelper.ts +++ b/src/migrations/ormHelper.ts @@ -1,5 +1,3 @@ -import { DB_TYPE } from "../env.defaults"; - export type ORMType = "int" | "bigint" | "boolean" | "date" | "datetime" | "time" | "text" | "varchar" | "uuid"; export type ORMDefault = "currentTimestamp" | "string" | "boolean" | "number" | "null"; export type ColumnConfig = { @@ -15,83 +13,38 @@ export type Primary = { }; export function getTypeByORM(type: ORMType, nullable: boolean = false, length: number = 255): ColumnConfig { - const dbType = DB_TYPE; - - const typeMap: Record> = { - mysql: { - int: "int", - bigint: "bigint", - boolean: "tinyint", - date: "date", - datetime: "datetime", - time: "time", - text: "text", - varchar: "varchar", - uuid: "varchar", - }, - postgres: { - int: "integer", - bigint: "bigint", - boolean: "boolean", - date: "date", - datetime: "timestamp", - time: "time", - text: "text", - varchar: "character varying", - uuid: "uuid", - }, - sqlite: { - int: "integer", - bigint: "integer", - boolean: "integer", - date: "date", - datetime: "datetime", - time: "text", - text: "text", - varchar: "varchar", - uuid: "varchar", - }, + const typeMap: Record = { + int: "integer", + bigint: "bigint", + boolean: "boolean", + date: "date", + datetime: "timestamp", + time: "time", + text: "text", + varchar: "character varying", + uuid: "uuid", }; let obj: ColumnConfig = { - type: typeMap[dbType]?.[type] || type, + type: typeMap[type] || type, isNullable: nullable, }; if (type == "datetime") obj.precision = length; - else if (dbType != "sqlite" && (obj.type == "varchar" || type == "varchar")) obj.length = `${length}`; - else if (dbType != "postgres" && type == "uuid") obj.length = "36"; + else if (obj.type == "varchar" || type == "varchar") obj.length = `${length}`; return obj; } export function getDefaultByORM(type: ORMDefault, data?: string | number | boolean): T { - const dbType = DB_TYPE; - - const typeMap: Record> = { - mysql: { - currentTimestamp: `CURRENT_TIMESTAMP(${data ?? 6})`, - string: `'${data ?? ""}'`, - boolean: Boolean(data).toString(), - number: Number(data).toString(), - null: null, - }, - postgres: { - currentTimestamp: `now()`, - string: `'${data ?? ""}'`, - boolean: Boolean(data) == true ? "true" : "false", - number: Number(data).toString(), - null: null, - }, - sqlite: { - currentTimestamp: `datetime('now')`, - string: `'${data ?? ""}'`, - boolean: Boolean(data) == true ? "1" : "0", - number: Number(data).toString(), - null: null, - }, + const typeMap: Record = { + currentTimestamp: `now()`, + string: `'${data ?? ""}'`, + boolean: Boolean(data) == true ? "true" : "false", + number: Number(data).toString(), + null: null, }; - return (typeMap[dbType]?.[type] || type) as T; + return (typeMap[type] || type) as T; } export const isIncrementPrimary: Primary = { diff --git a/src/service/club/member/memberService.ts b/src/service/club/member/memberService.ts index b6f4d5c..0aed9aa 100644 --- a/src/service/club/member/memberService.ts +++ b/src/service/club/member/memberService.ts @@ -3,7 +3,6 @@ import { dataSource } from "../../../data-source"; import { member } from "../../../entity/club/member/member"; import DatabaseActionException from "../../../exceptions/databaseActionException"; import { memberView } from "../../../views/memberView"; -import { DB_TYPE } from "../../../env.defaults"; export default abstract class MemberService { /** @@ -194,17 +193,13 @@ export default abstract class MemberService { "member.firstMembershipEntry", "member.memberships", "membership_first", - DB_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)" + 'membership_first.memberId = member.id AND membership_first.start = (SELECT MIN("m_first"."start") FROM "membership" "m_first" WHERE "m_first"."memberId" = "member"."id")' ) .leftJoinAndMapOne( "member.lastMembershipEntry", "member.memberships", "membership_last", - DB_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)" + 'membership_last.memberId = member.id AND membership_last.start = (SELECT MAX("m_last"."start") FROM "membership" "m_last" WHERE "m_last"."memberId" = "member"."id")' ) .leftJoinAndSelect("membership_first.status", "status_first") .leftJoinAndSelect("membership_last.status", "status_last") diff --git a/src/views/memberExecutivePositionView.ts b/src/views/memberExecutivePositionView.ts index 8b8f328..d7b1be5 100644 --- a/src/views/memberExecutivePositionView.ts +++ b/src/views/memberExecutivePositionView.ts @@ -1,36 +1,5 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions"; -import { DB_TYPE } from "../env.defaults"; - -let durationInDays: string; -let durationInYears: string; -let exactDuration: string; -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")))`; - exactDuration = `SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))`; -} else if (DB_TYPE == "mysql") { - durationInDays = `SUM(DATEDIFF(COALESCE(memberExecutivePositions.end, CURDATE()), memberExecutivePositions.start))`; - durationInYears = `SUM(TIMESTAMPDIFF(YEAR, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURDATE())))`; - exactDuration = ` - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURDATE())), 30))), - ' days' - ) - `; -} else if (DB_TYPE == "sqlite") { - durationInDays = `SUM(JULIANDAY(COALESCE(memberExecutivePositions.end, DATE('now'))) - JULIANDAY(memberExecutivePositions.start))`; - durationInYears = `SUM(FLOOR((JULIANDAY(COALESCE(memberExecutivePositions.end, DATE('now'))) - JULIANDAY(memberExecutivePositions.start)) / 365.25))`; - exactDuration = ` - SUM((strftime('%Y', COALESCE(memberExecutivePositions.end, DATE('now'))) - strftime('%Y', memberExecutivePositions.start))) || ' years ' || - SUM((strftime('%m', COALESCE(memberExecutivePositions.end, DATE('now'))) - strftime('%m', memberExecutivePositions.start))) || ' months ' || - SUM((strftime('%d', COALESCE(memberExecutivePositions.end, DATE('now'))) - strftime('%d', memberExecutivePositions.start))) || ' days' - `; -} @ViewEntity({ expression: (datasource: DataSource) => @@ -45,9 +14,18 @@ if (DB_TYPE == "postgres") { .addSelect("member.nameaffix", "memberNameaffix") .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") - .addSelect(durationInDays, "durationInDays") - .addSelect(durationInYears, "durationInYears") - .addSelect(exactDuration, "exactDuration") + .addSelect( + `SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start")`, + "durationInDays" + ) + .addSelect( + `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")))`, + "durationInYears" + ) + .addSelect( + `SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))`, + "exactDuration" + ) .leftJoin("memberExecutivePositions.executivePosition", "executivePosition") .leftJoin("memberExecutivePositions.member", "member") .leftJoin("member.salutation", "salutation") diff --git a/src/views/memberQualificationsView.ts b/src/views/memberQualificationsView.ts index 6f88f39..5111511 100644 --- a/src/views/memberQualificationsView.ts +++ b/src/views/memberQualificationsView.ts @@ -1,36 +1,5 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { memberQualifications } from "../entity/club/member/memberQualifications"; -import { DB_TYPE } from "../env.defaults"; - -let durationInDays: string; -let durationInYears: string; -let exactDuration: string; -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")))`; - exactDuration = `SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))`; -} else if (DB_TYPE == "mysql") { - durationInDays = `SUM(DATEDIFF(COALESCE(memberQualifications.end, CURDATE()), memberQualifications.start))`; - durationInYears = `SUM(TIMESTAMPDIFF(YEAR, memberQualifications.start, COALESCE(memberQualifications.end, CURDATE())))`; - exactDuration = ` - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, memberQualifications.start, COALESCE(memberQualifications.end, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURDATE())), 30))), - ' days' - ) - `; -} else if (DB_TYPE == "sqlite") { - durationInDays = `SUM(JULIANDAY(COALESCE(memberQualifications.end, DATE('now'))) - JULIANDAY(memberQualifications.start))`; - durationInYears = `SUM(FLOOR((JULIANDAY(COALESCE(memberQualifications.end, DATE('now'))) - JULIANDAY(memberQualifications.start)) / 365.25))`; - exactDuration = ` - SUM((strftime('%Y', COALESCE(memberQualifications.end, DATE('now'))) - strftime('%Y', memberQualifications.start))) || ' years ' || - SUM((strftime('%m', COALESCE(memberQualifications.end, DATE('now'))) - strftime('%m', memberQualifications.start))) || ' months ' || - SUM((strftime('%d', COALESCE(memberQualifications.end, DATE('now'))) - strftime('%d', memberQualifications.start))) || ' days' - `; -} @ViewEntity({ expression: (datasource: DataSource) => @@ -45,9 +14,18 @@ if (DB_TYPE == "postgres") { .addSelect("member.nameaffix", "memberNameaffix") .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") - .addSelect(durationInDays, "durationInDays") - .addSelect(durationInYears, "durationInYears") - .addSelect(exactDuration, "exactDuration") + .addSelect( + `SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start")`, + "durationInDays" + ) + .addSelect( + `SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")))`, + "durationInYears" + ) + .addSelect( + `SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))`, + "exactDuration" + ) .leftJoin("memberQualifications.qualification", "qualification") .leftJoin("memberQualifications.member", "member") .leftJoin("member.salutation", "salutation") diff --git a/src/views/memberView.ts b/src/views/memberView.ts index 260e0ff..1ffc058 100644 --- a/src/views/memberView.ts +++ b/src/views/memberView.ts @@ -1,39 +1,5 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { member } from "../entity/club/member/member"; -import { DB_TYPE } from "../env.defaults"; - -let todayAge: string; -let ageThisYear: string; -let exactAge: string; -if (DB_TYPE == "postgres") { - todayAge = `DATE_PART('year', AGE(CURRENT_DATE, member.birthdate))`; - ageThisYear = `EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate)`; - exactAge = `AGE(CURRENT_DATE, member.birthdate)`; -} else if (DB_TYPE == "mysql") { - todayAge = `TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE()) AS todayAge`; - ageThisYear = `YEAR(CURDATE()) - YEAR(member.birthdate) AS ageThisYear`; - exactAge = ` - CONCAT( - TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE()), ' years ', - TIMESTAMPDIFF(MONTH, member.birthdate, CURDATE()) % 12, ' months ', - TIMESTAMPDIFF(DAY, - DATE_ADD( - member.birthdate, - INTERVAL TIMESTAMPDIFF(MONTH, member.birthdate, CURDATE()) MONTH - ), - CURDATE() - ), ' days' - ) - `; -} else if (DB_TYPE == "sqlite") { - todayAge = `(strftime('%Y', 'now') - strftime('%Y', member.birthdate) - (strftime('%m-%d', 'now') < strftime('%m-%d', member.birthdate)))`; - ageThisYear = `strftime('%Y', 'now') - strftime('%Y', member.birthdate)`; - exactAge = ` - (strftime('%Y', 'now') - strftime('%Y', member.birthdate)) || ' years ' || - (strftime('%m', 'now') - strftime('%m', member.birthdate)) || ' months ' || - (strftime('%d', 'now') - strftime('%d', member.birthdate)) || ' days' - `; -} @ViewEntity({ expression: (datasource: DataSource) => @@ -48,9 +14,9 @@ if (DB_TYPE == "postgres") { .addSelect("member.nameaffix", "nameaffix") .addSelect("member.birthdate", "birthdate") .addSelect("salutation.salutation", "salutation") - .addSelect(todayAge, "todayAge") - .addSelect(ageThisYear, "ageThisYear") - .addSelect(exactAge, "exactAge") + .addSelect(`DATE_PART('year', AGE(CURRENT_DATE, member.birthdate))`, "todayAge") + .addSelect(`EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM member.birthdate)`, "ageThisYear") + .addSelect(`AGE(CURRENT_DATE, member.birthdate)`, "exactAge") .leftJoin("member.salutation", "salutation"), }) export class memberView { diff --git a/src/views/membershipsView.ts b/src/views/membershipsView.ts index 7807f8e..d64da63 100644 --- a/src/views/membershipsView.ts +++ b/src/views/membershipsView.ts @@ -1,36 +1,5 @@ import { DataSource, ViewColumn, ViewEntity } from "typeorm"; import { membership } from "../entity/club/member/membership"; -import { DB_TYPE } from "../env.defaults"; - -let durationInDays: string; -let durationInYears: string; -let exactDuration: string; -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")))`; - exactDuration = `SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))`; -} else if (DB_TYPE == "mysql") { - durationInDays = `SUM(DATEDIFF(COALESCE(membership.end, CURDATE()), membership.start))`; - durationInYears = `SUM(TIMESTAMPDIFF(YEAR, membership.start, COALESCE(membership.end, CURDATE())))`; - exactDuration = ` - CONCAT( - SUM(FLOOR(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURDATE())) / 365.25)), - ' years ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(MONTH, membership.start, COALESCE(membership.end, CURDATE())), 12))), - ' months ', - SUM(FLOOR(MOD(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURDATE())), 30))), - ' days' - ) - `; -} else if (DB_TYPE == "sqlite") { - durationInDays = `SUM(JULIANDAY(COALESCE(membership.end, DATE('now'))) - JULIANDAY(membership.start))`; - durationInYears = `SUM(FLOOR((JULIANDAY(COALESCE(membership.end, DATE('now'))) - JULIANDAY(membership.start)) / 365.25))`; - exactDuration = ` - SUM((strftime('%Y', COALESCE(membership.end, DATE('now'))) - strftime('%Y', membership.start))) || ' years ' || - SUM((strftime('%m', COALESCE(membership.end, DATE('now'))) - strftime('%m', membership.start))) || ' months ' || - SUM((strftime('%d', COALESCE(membership.end, DATE('now'))) - strftime('%d', membership.start))) || ' days' - `; -} @ViewEntity({ expression: (datasource: DataSource) => @@ -45,9 +14,12 @@ if (DB_TYPE == "postgres") { .addSelect("member.nameaffix", "memberNameaffix") .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") - .addSelect(durationInDays, "durationInDays") - .addSelect(durationInYears, "durationInYears") - .addSelect(exactDuration, "exactDuration") + .addSelect(`SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") `, "durationInDays") + .addSelect( + `SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")))`, + "durationInYears" + ) + .addSelect(`SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))`, "exactDuration") .leftJoin("membership.status", "status") .leftJoin("membership.member", "member") .leftJoin("member.salutation", "salutation") @@ -101,14 +73,17 @@ export class membershipView { .addSelect("member.nameaffix", "memberNameaffix") .addSelect("member.birthdate", "memberBirthdate") .addSelect("salutation.salutation", "memberSalutation") - .addSelect(durationInDays, "durationInDays") - .addSelect(durationInYears, "durationInYears") - .addSelect(exactDuration, "exactDuration") + .addSelect(`SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") `, "durationInDays") + .addSelect( + `SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")))`, + "durationInYears" + ) + .addSelect(`SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))`, "exactDuration") .leftJoin("membership.status", "status") .leftJoin("membership.member", "member") .leftJoin("member.salutation", "salutation") - .groupBy("status.id") - .addGroupBy("member.id"), + .groupBy("member.id") + .addGroupBy("salutation.id"), }) export class membershipTotalView { @ViewColumn() From 874b863b1e9e08a0d1ec94869ff01f7446f9e429 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 7 Jun 2025 15:25:41 +0200 Subject: [PATCH 2/5] update package.json --- package-lock.json | 248 ++++++++++++++-------- package.json | 3 - src/entity/club/member/member.ts | 4 +- src/migrations/baseSchemaTables/member.ts | 2 +- 4 files changed, 159 insertions(+), 98 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3d33297..b059721 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,6 @@ "morgan": "^1.10.0", "ms": "^2.1.3", "multer": "^1.4.5-lts.2", - "mysql": "^2.18.1", "node-schedule": "^2.1.1", "nodemailer": "^7.0.2", "pdf-lib": "^1.17.1", @@ -39,7 +38,6 @@ "sharp-ico": "^0.1.5", "socket.io": "^4.8.1", "speakeasy": "^2.0.0", - "sqlite3": "^5.1.7", "typeorm": "^0.3.22", "uuid": "^11.1.0", "validator": "^13.15.0" @@ -54,7 +52,6 @@ "@types/morgan": "^1.9.9", "@types/ms": "^2.1.0", "@types/multer": "^1.4.12", - "@types/mysql": "^2.15.27", "@types/node": "^22.15.12", "@types/node-schedule": "^2.1.7", "@types/nodemailer": "^6.4.17", @@ -131,7 +128,8 @@ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.34.1", @@ -640,6 +638,7 @@ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -652,6 +651,7 @@ "deprecated": "This functionality has been moved to @npmcli/fs", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -666,6 +666,7 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "license": "MIT", "optional": true, + "peer": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -740,6 +741,7 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 6" } @@ -922,16 +924,6 @@ "@types/express": "*" } }, - "node_modules/@types/mysql": { - "version": "2.15.27", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz", - "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { "version": "22.15.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.12.tgz", @@ -1059,7 +1051,8 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/accepts": { "version": "2.0.0", @@ -1115,6 +1108,7 @@ "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "humanize-ms": "^1.2.1" }, @@ -1128,6 +1122,7 @@ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1189,7 +1184,8 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/are-we-there-yet": { "version": "3.0.1", @@ -1198,6 +1194,7 @@ "deprecated": "This package is no longer supported.", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -1212,6 +1209,7 @@ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -1398,20 +1396,13 @@ "node": ">=10.0.0" } }, - "node_modules/bignumber.js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", - "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "file-uri-to-path": "1.0.0" } @@ -1421,6 +1412,8 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -1446,6 +1439,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -1456,6 +1451,8 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -1491,6 +1488,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1567,6 +1565,7 @@ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -1597,6 +1596,7 @@ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -1610,6 +1610,7 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "license": "MIT", "optional": true, + "peer": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -1669,6 +1670,8 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "license": "ISC", + "optional": true, + "peer": true, "engines": { "node": ">=10" } @@ -1692,6 +1695,7 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -1757,6 +1761,7 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "license": "ISC", "optional": true, + "peer": true, "bin": { "color-support": "bin.js" } @@ -1766,7 +1771,8 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -1788,7 +1794,8 @@ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/content-disposition": { "version": "1.0.0", @@ -1987,6 +1994,8 @@ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -2002,6 +2011,8 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=4.0.0" } @@ -2025,7 +2036,8 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/depd": { "version": "2.0.0", @@ -2135,6 +2147,7 @@ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -2281,7 +2294,8 @@ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/error-ex": { "version": "1.3.2", @@ -2403,6 +2417,8 @@ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "license": "(MIT OR WTFPL)", + "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -2525,7 +2541,9 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/finalhandler": { "version": "2.1.0", @@ -2607,13 +2625,17 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -2626,7 +2648,8 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/function-bind": { "version": "1.1.2", @@ -2644,6 +2667,7 @@ "deprecated": "This package is no longer supported.", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -2737,7 +2761,9 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/glob": { "version": "7.2.3", @@ -2746,6 +2772,7 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2778,7 +2805,8 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/handlebars": { "version": "4.7.8", @@ -2818,7 +2846,8 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/hasown": { "version": "2.0.2", @@ -2846,7 +2875,8 @@ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "license": "BSD-2-Clause", - "optional": true + "optional": true, + "peer": true }, "node_modules/http-errors": { "version": "2.0.0", @@ -2896,6 +2926,7 @@ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "ms": "^2.0.0" } @@ -2971,6 +3002,7 @@ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=0.8.19" } @@ -2981,6 +3013,7 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -2990,7 +3023,8 @@ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/inflight": { "version": "1.0.6", @@ -2999,6 +3033,7 @@ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3014,7 +3049,9 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC" + "license": "ISC", + "optional": true, + "peer": true }, "node_modules/ip": { "version": "2.0.1", @@ -3064,7 +3101,8 @@ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/is-promise": { "version": "4.0.0", @@ -3287,6 +3325,7 @@ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -3315,6 +3354,7 @@ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "debug": "4" }, @@ -3328,6 +3368,7 @@ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -3343,6 +3384,7 @@ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -3357,6 +3399,7 @@ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -3370,6 +3413,7 @@ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -3380,6 +3424,7 @@ "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -3445,6 +3490,8 @@ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10" }, @@ -3458,6 +3505,7 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3479,6 +3527,8 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -3492,6 +3542,7 @@ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -3505,6 +3556,7 @@ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -3523,6 +3575,7 @@ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -3536,6 +3589,7 @@ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -3549,6 +3603,7 @@ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -3561,6 +3616,8 @@ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -3591,7 +3648,9 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/moment": { "version": "2.30.1", @@ -3712,42 +3771,6 @@ "node": ">= 0.6" } }, - "node_modules/mysql": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", - "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", - "license": "MIT", - "dependencies": { - "bignumber.js": "9.0.0", - "readable-stream": "2.3.7", - "safe-buffer": "5.1.2", - "sqlstring": "2.3.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mysql/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/mysql/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -3770,7 +3793,9 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/negotiator": { "version": "1.0.0", @@ -3801,6 +3826,8 @@ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "semver": "^7.3.5" }, @@ -3812,7 +3839,9 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/node-gyp": { "version": "8.4.1", @@ -3820,6 +3849,7 @@ "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -3868,6 +3898,7 @@ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "abbrev": "1" }, @@ -3885,6 +3916,7 @@ "deprecated": "This package is no longer supported.", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -3986,6 +4018,7 @@ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -4103,6 +4136,7 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -4401,6 +4435,8 @@ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -4426,13 +4462,17 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" + "license": "ISC", + "optional": true, + "peer": true }, "node_modules/prebuild-install/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -4447,6 +4487,8 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -4459,6 +4501,8 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -4490,7 +4534,8 @@ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/promise-retry": { "version": "2.0.1", @@ -4498,6 +4543,7 @@ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -4725,6 +4771,8 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "peer": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -4792,6 +4840,7 @@ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 4" } @@ -4803,6 +4852,7 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -5100,7 +5150,8 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/simple-concat": { "version": "1.0.1", @@ -5120,7 +5171,9 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/simple-get": { "version": "4.0.1", @@ -5141,6 +5194,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -5420,6 +5475,8 @@ "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", "hasInstallScript": true, "license": "BSD-3-Clause", + "optional": true, + "peer": true, "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^7.0.0", @@ -5438,21 +5495,13 @@ } } }, - "node_modules/sqlstring": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", - "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "minipass": "^3.1.1" }, @@ -5564,6 +5613,8 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5573,6 +5624,8 @@ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -5615,6 +5668,8 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "license": "ISC", + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -5624,6 +5679,8 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "license": "MIT", + "optional": true, + "peer": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -5722,6 +5779,8 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -5970,6 +6029,7 @@ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "unique-slug": "^2.0.0" } @@ -5980,6 +6040,7 @@ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "imurmurhash": "^0.1.4" } @@ -6064,6 +6125,7 @@ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "license": "ISC", "optional": true, + "peer": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -6180,7 +6242,9 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "license": "ISC", + "optional": true, + "peer": true }, "node_modules/yargs": { "version": "17.7.2", diff --git a/package.json b/package.json index faa74d8..f1c2150 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "morgan": "^1.10.0", "ms": "^2.1.3", "multer": "^1.4.5-lts.2", - "mysql": "^2.18.1", "node-schedule": "^2.1.1", "nodemailer": "^7.0.2", "pdf-lib": "^1.17.1", @@ -55,7 +54,6 @@ "sharp-ico": "^0.1.5", "socket.io": "^4.8.1", "speakeasy": "^2.0.0", - "sqlite3": "^5.1.7", "typeorm": "^0.3.22", "uuid": "^11.1.0", "validator": "^13.15.0" @@ -70,7 +68,6 @@ "@types/morgan": "^1.9.9", "@types/ms": "^2.1.0", "@types/multer": "^1.4.12", - "@types/mysql": "^2.15.27", "@types/node": "^22.15.12", "@types/node-schedule": "^2.1.7", "@types/nodemailer": "^6.4.17", diff --git a/src/entity/club/member/member.ts b/src/entity/club/member/member.ts index 57d8bb6..0720f57 100644 --- a/src/entity/club/member/member.ts +++ b/src/entity/club/member/member.ts @@ -39,8 +39,8 @@ export class member { @Column({ type: "varchar", length: 255, unique: true, nullable: true }) internalId?: string; - @Column({ type: "varchar", length: 255 }) - note: string; + @Column({ type: "varchar", length: 255, nullable: true }) + note?: string; @Column() salutationId: number; diff --git a/src/migrations/baseSchemaTables/member.ts b/src/migrations/baseSchemaTables/member.ts index 26d02a5..be77d69 100644 --- a/src/migrations/baseSchemaTables/member.ts +++ b/src/migrations/baseSchemaTables/member.ts @@ -72,7 +72,7 @@ export const member_table = new Table({ { name: "nameaffix", ...getTypeByORM("varchar") }, { name: "birthdate", ...getTypeByORM("date") }, { name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp", 6) }, - { name: "note", ...getTypeByORM("varchar") }, + { name: "note", ...getTypeByORM("varchar", true) }, ], foreignKeys: [ new TableForeignKey({ From feb03ba99d1b82cde0170ffbd246511b8fccbee3 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 7 Jun 2025 15:38:34 +0200 Subject: [PATCH 3/5] better insert template usage scopes --- src/migrations/1749296280721-CreateSchema.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/migrations/1749296280721-CreateSchema.ts b/src/migrations/1749296280721-CreateSchema.ts index 168810a..638455c 100644 --- a/src/migrations/1749296280721-CreateSchema.ts +++ b/src/migrations/1749296280721-CreateSchema.ts @@ -49,6 +49,7 @@ import { protocol_printout_table, } from "./baseSchemaTables/protocol"; import { query_table, template_table, template_usage_table } from "./baseSchemaTables/query_template"; +import { availableTemplates } from "../type/templateTypes"; export class CreateSchema1749296280721 implements MigrationInterface { name = "CreateSchema1749296280721"; @@ -95,13 +96,11 @@ export class CreateSchema1749296280721 implements MigrationInterface { .createQueryBuilder() .insert() .into(template_usage_table.name) - .values([ - { scope: "newsletter" }, - { scope: "protocol" }, - { scope: "member" }, - { scope: "listprint" }, - { scope: "listprint.member" }, - ]) + .values( + availableTemplates.map((at) => ({ + scope: at, + })) + ) .orIgnore() .execute(); From dc43df8937667a49c4978b5bbc7648ee1c8d0fb7 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 7 Jun 2025 15:38:56 +0200 Subject: [PATCH 4/5] fix: spelling of invite orUpdate --- src/command/management/user/inviteCommandHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command/management/user/inviteCommandHandler.ts b/src/command/management/user/inviteCommandHandler.ts index 5c01044..2e341c2 100644 --- a/src/command/management/user/inviteCommandHandler.ts +++ b/src/command/management/user/inviteCommandHandler.ts @@ -26,7 +26,7 @@ export default abstract class InviteCommandHandler { lastname: createInvite.lastname, secret: createInvite.secret, }) - .orUpdate(["firstName", "lastName", "token", "secret"], ["mail"]) + .orUpdate(["firstname", "lastname", "token", "secret"], ["mail"]) .execute() .then((result) => { return token; From de6ed4fba86458ba4a461b7c93e6944ee11df3ca Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 7 Jun 2025 15:44:44 +0200 Subject: [PATCH 5/5] update packages --- package-lock.json | 596 ++++++++++++++++++---------------------------- package.json | 28 +-- 2 files changed, 250 insertions(+), 374 deletions(-) diff --git a/package-lock.json b/package-lock.json index b059721..51602f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,41 +25,41 @@ "moment": "^2.30.1", "morgan": "^1.10.0", "ms": "^2.1.3", - "multer": "^1.4.5-lts.2", + "multer": "^2.0.1", "node-schedule": "^2.1.1", - "nodemailer": "^7.0.2", + "nodemailer": "^7.0.3", "pdf-lib": "^1.17.1", - "pg": "^8.15.6", - "puppeteer": "^24.8.0", + "pg": "^8.16.0", + "puppeteer": "^24.10.0", "qrcode": "^1.5.4", "reflect-metadata": "^0.2.2", "rss-parser": "^3.13.0", - "sharp": "^0.34.1", + "sharp": "^0.34.2", "sharp-ico": "^0.1.5", "socket.io": "^4.8.1", "speakeasy": "^2.0.0", - "typeorm": "^0.3.22", + "typeorm": "^0.3.24", "uuid": "^11.1.0", - "validator": "^13.15.0" + "validator": "^13.15.15" }, "devDependencies": { - "@types/cors": "^2.8.17", - "@types/express": "^5.0.1", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", "@types/ip": "^1.1.3", "@types/jsonwebtoken": "^9.0.9", "@types/lodash.clonedeep": "^4.5.9", "@types/lodash.uniqby": "^4.7.9", - "@types/morgan": "^1.9.9", + "@types/morgan": "^1.9.10", "@types/ms": "^2.1.0", - "@types/multer": "^1.4.12", - "@types/node": "^22.15.12", + "@types/multer": "^1.4.13", + "@types/node": "^22.15.30", "@types/node-schedule": "^2.1.7", "@types/nodemailer": "^6.4.17", - "@types/pg": "~8.12.0", + "@types/pg": "~8.15.4", "@types/qrcode": "~1.5.5", "@types/speakeasy": "^2.0.10", "@types/uuid": "^10.0.0", - "@types/validator": "^13.15.0", + "@types/validator": "^13.15.1", "ts-node": "10.9.2", "typescript": "^5.8.3" } @@ -132,9 +132,9 @@ "peer": true }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz", - "integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", + "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", "cpu": [ "arm64" ], @@ -154,9 +154,9 @@ } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz", - "integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", + "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", "cpu": [ "x64" ], @@ -320,9 +320,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz", - "integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", + "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", "cpu": [ "arm" ], @@ -342,9 +342,9 @@ } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz", - "integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", + "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", "cpu": [ "arm64" ], @@ -364,9 +364,9 @@ } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz", - "integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", + "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", "cpu": [ "s390x" ], @@ -386,9 +386,9 @@ } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz", - "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", + "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", "cpu": [ "x64" ], @@ -408,9 +408,9 @@ } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz", - "integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", + "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", "cpu": [ "arm64" ], @@ -430,9 +430,9 @@ } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz", - "integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", + "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", "cpu": [ "x64" ], @@ -452,16 +452,16 @@ } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz", - "integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", + "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.4.0" + "@emnapi/runtime": "^1.4.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -470,10 +470,29 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", + "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz", - "integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", + "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", "cpu": [ "ia32" ], @@ -490,9 +509,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz", - "integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", + "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", "cpu": [ "x64" ], @@ -703,16 +722,16 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.3.tgz", - "integrity": "sha512-iPpnFpX25gKIVsHsqVjHV+/GzW36xPgsscWkCnrrETndcdxNsXLdCrTwhkCJNR/FGWr122dJUBeyV4niz/j3TA==", + "version": "2.10.5", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz", + "integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==", "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.0", + "debug": "^4.4.1", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", - "semver": "^7.7.1", + "semver": "^7.7.2", "tar-fs": "^3.0.8", "yargs": "^17.7.2" }, @@ -802,18 +821,18 @@ } }, "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/express": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.1.tgz", - "integrity": "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", "dev": true, "license": "MIT", "dependencies": { @@ -898,9 +917,9 @@ "license": "MIT" }, "node_modules/@types/morgan": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", - "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz", + "integrity": "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA==", "dev": true, "license": "MIT", "dependencies": { @@ -915,9 +934,9 @@ "license": "MIT" }, "node_modules/@types/multer": { - "version": "1.4.12", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", - "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.13.tgz", + "integrity": "sha512-bhhdtPw7JqCiEfC9Jimx5LqX9BDIPJEh2q/fQ4bqbBPtyEZYr3cvF22NwG0DmPZNYA0CAf2CnqDB4KIGGpJcaw==", "dev": true, "license": "MIT", "dependencies": { @@ -925,9 +944,9 @@ } }, "node_modules/@types/node": { - "version": "22.15.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.12.tgz", - "integrity": "sha512-K0fpC/ZVeb8G9rm7bH7vI0KAec4XHEhBam616nVJCV51bKzJ6oA3luG4WdKoaztxe70QaNjS/xBmcDLmr4PiGw==", + "version": "22.15.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", + "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -954,15 +973,15 @@ } }, "node_modules/@types/pg": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.12.0.tgz", - "integrity": "sha512-a9Z11ecnpNPFu2iT4Qo9SSYgM2r1l4UqLIQ454zhCDRzxqOh/vsi57FFovbc64oBGPBotXw5cRhUQtJEHCb/OA==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.4.tgz", + "integrity": "sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "pg-protocol": "*", - "pg-types": "^4.0.1" + "pg-types": "^2.2.0" } }, "node_modules/@types/qrcode": { @@ -1030,9 +1049,9 @@ "license": "MIT" }, "node_modules/@types/validator": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.0.tgz", - "integrity": "sha512-nh7nrWhLr6CBq9ldtw0wx+z9wKnnv/uTVLA9g/3/TcOYxbpOSZE+MhKPmWqU+K0NvThjhv12uD8MuqijB0WzEA==", + "version": "13.15.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.1.tgz", + "integrity": "sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==", "dev": true, "license": "MIT" }, @@ -1203,22 +1222,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -1270,9 +1273,9 @@ "optional": true }, "node_modules/bare-fs": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.4.tgz", - "integrity": "sha512-r8+26Voz8dGX3AYpJdFb1ZPaUSM8XOLCZvy+YGpRTmwPHIxA7Z3Jov/oMPtV7hfRQbOnH8qGlLTzQAbgtdNN0Q==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.5.tgz", + "integrity": "sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1446,22 +1449,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/body-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", @@ -1677,9 +1664,9 @@ } }, "node_modules/chromium-bidi": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-4.1.1.tgz", - "integrity": "sha512-biR7t4vF3YluE6RlMSk9IWk+b9U+WWyzHp+N2pL9vRTk+UXHYRTVp7jTK58ZNzMLBgoLMHY4QyJMbeuw3eKxqg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz", + "integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==", "license": "Apache-2.0", "dependencies": { "mitt": "^3.0.1", @@ -1775,17 +1762,17 @@ "peer": true }, "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "engines": [ - "node >= 0.8" + "node >= 6.0" ], "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", - "readable-stream": "^2.2.2", + "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, @@ -1836,12 +1823,6 @@ "node": ">=6.6.0" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" - }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -1937,9 +1918,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2006,6 +1987,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -2058,9 +2053,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1439962", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1439962.tgz", - "integrity": "sha512-jJF48UdryzKiWhJ1bLKr7BFWUQCEIT5uCNbDLqkQJBtkFxYzILJH44WN0PDKMIlGDN7Utb8vyUY85C3w4R/t2g==", + "version": "0.0.1452169", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1452169.tgz", + "integrity": "sha512-FOFDVMGrAUNp0dDKsAU1TorWJUx2JOU1k9xdgBKKJF3IBh/Uhl2yswG5r3TEAOrCiGY2QRp1e6LVDQrCsTKO4g==", "license": "BSD-3-Clause" }, "node_modules/diff": { @@ -3110,12 +3105,6 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3711,21 +3700,21 @@ "license": "MIT" }, "node_modules/multer": { - "version": "1.4.5-lts.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", - "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.1.tgz", + "integrity": "sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" + "type-is": "^1.6.18", + "xtend": "^4.0.2" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 10.16.0" } }, "node_modules/multer/node_modules/media-typer": { @@ -3884,9 +3873,9 @@ } }, "node_modules/nodemailer": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.2.tgz", - "integrity": "sha512-SYsisPeLFYli5Q+BCGSyHT5CVvezPmQjHgINV9KVvVLV1aktuoD4E0Np9Q3ND9I481qIHzUQzVT+Tl/Tw7Ivdg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.3.tgz", + "integrity": "sha512-Ajq6Sz1x7cIK3pN6KesGTah+1gnwMnx5gKl3piQlQQE/PwyJ4Mbc8is2psWYxK3RJTVeqsDaCv8ZzXLCDHMTZw==", "license": "MIT-0", "engines": { "node": ">=6.0.0" @@ -3948,13 +3937,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true, - "license": "MIT" - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -4209,16 +4191,16 @@ "license": "MIT" }, "node_modules/pg": { - "version": "8.15.6", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.15.6.tgz", - "integrity": "sha512-yvao7YI3GdmmrslNVsZgx9PfntfWrnXwtR+K/DjI0I/sTKif4Z623um+sjVZ1hk5670B+ODjvHDAckKdjmPTsg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.0.tgz", + "integrity": "sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg==", "license": "MIT", "dependencies": { - "pg-connection-string": "^2.8.5", - "pg-pool": "^3.9.6", - "pg-protocol": "^1.9.5", - "pg-types": "^2.1.0", - "pgpass": "1.x" + "pg-connection-string": "^2.9.0", + "pg-pool": "^3.10.0", + "pg-protocol": "^1.10.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" }, "engines": { "node": ">= 8.0.0" @@ -4243,9 +4225,9 @@ "optional": true }, "node_modules/pg-connection-string": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.8.5.tgz", - "integrity": "sha512-Ni8FuZ8yAF+sWZzojvtLE2b03cqjO5jNULcHFfM9ZZ0/JXrgom5pBREbtnAw7oxsxJqHw9Nz/XWORUEL3/IFow==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.0.tgz", + "integrity": "sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==", "license": "MIT" }, "node_modules/pg-int8": { @@ -4257,51 +4239,22 @@ "node": ">=4.0.0" } }, - "node_modules/pg-numeric": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", - "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=4" - } - }, "node_modules/pg-pool": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.9.6.tgz", - "integrity": "sha512-rFen0G7adh1YmgvrmE5IPIqbb+IgEzENUm+tzm6MLLDSlPRoZVhzU1WdML9PV2W5GOdRA9qBKURlbt1OsXOsPw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.0.tgz", + "integrity": "sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA==", "license": "MIT", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.9.5.tgz", - "integrity": "sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.0.tgz", + "integrity": "sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q==", "license": "MIT" }, "node_modules/pg-types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", - "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", - "dev": true, - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "pg-numeric": "1.0.2", - "postgres-array": "~3.0.1", - "postgres-bytea": "~3.0.0", - "postgres-date": "~2.1.0", - "postgres-interval": "^3.0.0", - "postgres-range": "^1.1.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pg/node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", @@ -4317,45 +4270,6 @@ "node": ">=4" } }, - "node_modules/pg/node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pg/node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pg/node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pg/node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pgpass": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", @@ -4381,55 +4295,44 @@ } }, "node_modules/postgres-array": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz", - "integrity": "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=4" } }, "node_modules/postgres-bytea": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", - "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", - "dev": true, + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", "license": "MIT", - "dependencies": { - "obuf": "~1.1.2" - }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, "node_modules/postgres-date": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", - "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", - "dev": true, + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, "node_modules/postgres-interval": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", - "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", - "dev": true, + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/postgres-range": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", - "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", - "dev": true, - "license": "MIT" - }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -4466,26 +4369,10 @@ "optional": true, "peer": true }, - "node_modules/prebuild-install/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "license": "MIT", "optional": true, "peer": true, @@ -4514,12 +4401,6 @@ "node": ">=6" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" - }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -4607,17 +4488,17 @@ } }, "node_modules/puppeteer": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.8.0.tgz", - "integrity": "sha512-8GPlUKXvZK8ANxab75UerMar14ZnJTJpPok3XN9Nx6f7SKyabyFK39pQruMni6zfrwVBrPXp3Mo6ztwKEmXaDQ==", + "version": "24.10.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.10.0.tgz", + "integrity": "sha512-Oua9VkGpj0S2psYu5e6mCer6W9AU9POEQh22wRgSXnLXASGH+MwLUVWgLCLeP9QPHHcJ7tySUlg4Sa9OJmaLpw==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.3", - "chromium-bidi": "4.1.1", + "@puppeteer/browsers": "2.10.5", + "chromium-bidi": "5.1.0", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1439962", - "puppeteer-core": "24.8.0", + "devtools-protocol": "0.0.1452169", + "puppeteer-core": "24.10.0", "typed-query-selector": "^2.12.0" }, "bin": { @@ -4628,17 +4509,17 @@ } }, "node_modules/puppeteer-core": { - "version": "24.8.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.8.0.tgz", - "integrity": "sha512-tDf2YKIo5kM5r0vOzT52+PTgN0bBZOA4OFgQaqYyfarrcXLLJ92wi/lSMe44hd+F+gk0gw9QsAzyRW8v6ra93w==", + "version": "24.10.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.10.0.tgz", + "integrity": "sha512-xX0QJRc8t19iAwRDsAOR38Q/Zx/W6WVzJCEhKCAwp2XMsaWqfNtQ+rBfQW9PlF+Op24d7c8Zlgq9YNmbnA7hdQ==", "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.3", - "chromium-bidi": "4.1.1", - "debug": "^4.4.0", - "devtools-protocol": "0.0.1439962", + "@puppeteer/browsers": "2.10.5", + "chromium-bidi": "5.1.0", + "debug": "^4.4.1", + "devtools-protocol": "0.0.1452169", "typed-query-selector": "^2.12.0", - "ws": "^8.18.1" + "ws": "^8.18.2" }, "engines": { "node": ">=18" @@ -4784,26 +4665,19 @@ } }, "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/reflect-metadata": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", @@ -4928,9 +4802,9 @@ "license": "ISC" }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5002,15 +4876,15 @@ } }, "node_modules/sharp": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz", - "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==", + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", + "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.7.1" + "detect-libc": "^2.0.4", + "semver": "^7.7.2" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -5019,8 +4893,8 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.1", - "@img/sharp-darwin-x64": "0.34.1", + "@img/sharp-darwin-arm64": "0.34.2", + "@img/sharp-darwin-x64": "0.34.2", "@img/sharp-libvips-darwin-arm64": "1.1.0", "@img/sharp-libvips-darwin-x64": "1.1.0", "@img/sharp-libvips-linux-arm": "1.1.0", @@ -5030,15 +4904,16 @@ "@img/sharp-libvips-linux-x64": "1.1.0", "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.1", - "@img/sharp-linux-arm64": "0.34.1", - "@img/sharp-linux-s390x": "0.34.1", - "@img/sharp-linux-x64": "0.34.1", - "@img/sharp-linuxmusl-arm64": "0.34.1", - "@img/sharp-linuxmusl-x64": "0.34.1", - "@img/sharp-wasm32": "0.34.1", - "@img/sharp-win32-ia32": "0.34.1", - "@img/sharp-win32-x64": "0.34.1" + "@img/sharp-linux-arm": "0.34.2", + "@img/sharp-linux-arm64": "0.34.2", + "@img/sharp-linux-s390x": "0.34.2", + "@img/sharp-linux-x64": "0.34.2", + "@img/sharp-linuxmusl-arm64": "0.34.2", + "@img/sharp-linuxmusl-x64": "0.34.2", + "@img/sharp-wasm32": "0.34.2", + "@img/sharp-win32-arm64": "0.34.2", + "@img/sharp-win32-ia32": "0.34.2", + "@img/sharp-win32-x64": "0.34.2" } }, "node_modules/sharp-ico": { @@ -5527,9 +5402,9 @@ } }, "node_modules/streamx": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", - "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz", + "integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==", "license": "MIT", "dependencies": { "fast-fifo": "^1.3.2", @@ -5639,9 +5514,9 @@ } }, "node_modules/tar-fs": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", - "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", + "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -5827,9 +5702,9 @@ "license": "MIT" }, "node_modules/typeorm": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.22.tgz", - "integrity": "sha512-P/Tsz3UpJ9+K0oryC0twK5PO27zejLYYwMsE8SISfZc1lVHX+ajigiOyWsKbuXpEFMjD9z7UjLzY3+ElVOMMDA==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.24.tgz", + "integrity": "sha512-4IrHG7A0tY8l5gEGXfW56VOMfUVWEkWlH/h5wmcyZ+V8oCiLj7iTPp0lEjMEZVrxEkGSdP9ErgTKHKXQApl/oA==", "license": "MIT", "dependencies": { "@sqltools/formatter": "^1.2.5", @@ -5838,6 +5713,7 @@ "buffer": "^6.0.3", "dayjs": "^1.11.13", "debug": "^4.4.0", + "dedent": "^1.6.0", "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.11", @@ -6081,9 +5957,9 @@ "license": "MIT" }, "node_modules/validator": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz", - "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==", + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -6306,9 +6182,9 @@ } }, "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "version": "3.25.56", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.56.tgz", + "integrity": "sha512-rd6eEF3BTNvQnR2e2wwolfTmUTnp70aUTqr0oaGbHifzC3BKJsoV+Gat8vxUMR1hwOKBs6El+qWehrHbCpW6SQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index f1c2150..27fef07 100644 --- a/package.json +++ b/package.json @@ -41,41 +41,41 @@ "moment": "^2.30.1", "morgan": "^1.10.0", "ms": "^2.1.3", - "multer": "^1.4.5-lts.2", + "multer": "^2.0.1", "node-schedule": "^2.1.1", - "nodemailer": "^7.0.2", + "nodemailer": "^7.0.3", "pdf-lib": "^1.17.1", - "pg": "^8.15.6", - "puppeteer": "^24.8.0", + "pg": "^8.16.0", + "puppeteer": "^24.10.0", "qrcode": "^1.5.4", "reflect-metadata": "^0.2.2", "rss-parser": "^3.13.0", - "sharp": "^0.34.1", + "sharp": "^0.34.2", "sharp-ico": "^0.1.5", "socket.io": "^4.8.1", "speakeasy": "^2.0.0", - "typeorm": "^0.3.22", + "typeorm": "^0.3.24", "uuid": "^11.1.0", - "validator": "^13.15.0" + "validator": "^13.15.15" }, "devDependencies": { - "@types/cors": "^2.8.17", - "@types/express": "^5.0.1", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", "@types/ip": "^1.1.3", "@types/jsonwebtoken": "^9.0.9", "@types/lodash.clonedeep": "^4.5.9", "@types/lodash.uniqby": "^4.7.9", - "@types/morgan": "^1.9.9", + "@types/morgan": "^1.9.10", "@types/ms": "^2.1.0", - "@types/multer": "^1.4.12", - "@types/node": "^22.15.12", + "@types/multer": "^1.4.13", + "@types/node": "^22.15.30", "@types/node-schedule": "^2.1.7", "@types/nodemailer": "^6.4.17", - "@types/pg": "~8.12.0", + "@types/pg": "~8.15.4", "@types/qrcode": "~1.5.5", "@types/speakeasy": "^2.0.10", "@types/uuid": "^10.0.0", - "@types/validator": "^13.15.0", + "@types/validator": "^13.15.1", "ts-node": "10.9.2", "typescript": "^5.8.3" }