diff --git a/backend/package.json b/backend/package.json index 4606f345e..a84cb13af 100644 --- a/backend/package.json +++ b/backend/package.json @@ -36,26 +36,27 @@ "@nestjs/platform-ws": "10.4.15", "@nestjs/schedule": "4.1.2", "@nestjs/swagger": "8.0.7", - "@nestjs/typeorm": "10.0.2", "@nestjs/websockets": "10.4.15", "@node-rs/argon2": "2.0.2", "@zxcvbn-ts/core": "3.0.4", "@zxcvbn-ts/language-common": "3.0.4", "@zxcvbn-ts/language-en": "3.0.2", "base32-encode": "1.2.0", + "better-sqlite3": "11.8.1", "class-transformer": "0.5.1", "class-validator": "0.14.1", "cli-color": "2.0.4", - "connect-typeorm": "2.0.0", "cookie": "1.0.2", "diff": "7.0.0", "express-session": "1.18.1", "file-type": "16.5.4", "htmlparser2": "9.1.0", + "knex": "3.1.0", "ldapauth-fork": "6.1.0", "markdown-it": "13.0.2", "minio": "8.0.4", "mysql": "2.18.1", + "nestjs-knex": "2.0.0", "nestjs-zod": "4.3.1", "node-fetch": "2.7.0", "openid-client": "5.7.1", @@ -64,8 +65,6 @@ "reflect-metadata": "0.2.2", "rimraf": "6.0.1", "rxjs": "7.8.1", - "sqlite3": "5.1.7", - "typeorm": "0.3.20", "uuid": "11.0.5", "ws": "8.18.0", "yjs": "13.6.23", @@ -78,6 +77,7 @@ "@nestjs/testing": "10.4.15", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@tsconfig/node18": "18.2.4", + "@types/better-sqlite3": "7.6.12", "@types/cli-color": "2.0.6", "@types/cookie": "1.0.0", "@types/cookie-signature": "1.1.2", diff --git a/backend/src/api-token/api-token.entity.ts b/backend/src/api-token/api-token.entity.ts deleted file mode 100644 index adf56dfd1..000000000 --- a/backend/src/api-token/api-token.entity.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { User } from '../users/user.entity'; - -@Entity() -export class ApiToken { - @PrimaryGeneratedColumn() - id: number; - - @Column({ unique: true }) - keyId: string; - - @ManyToOne((_) => User, (user) => user.apiTokens, { - onDelete: 'CASCADE', // This deletes the PublicAuthToken, when the associated User is deleted - }) - user: Promise; - - @Column() - label: string; - - @CreateDateColumn() - createdAt: Date; - - @Column({ unique: true }) - hash: string; - - @Column() - validUntil: Date; - - @Column({ - nullable: true, - type: 'date', - }) - lastUsedAt: Date | null; - - public static create( - keyId: string, - user: User, - label: string, - tokenString: string, - validUntil: Date, - ): Omit { - const token = new ApiToken(); - token.keyId = keyId; - token.user = Promise.resolve(user); - token.label = label; - token.hash = tokenString; - token.validUntil = validUntil; - token.lastUsedAt = null; - return token; - } -} diff --git a/backend/src/api-token/api-token.service.spec.ts b/backend/src/api-token/api-token.service.spec.ts index a4bea44b4..4c56491b5 100644 --- a/backend/src/api-token/api-token.service.spec.ts +++ b/backend/src/api-token/api-token.service.spec.ts @@ -12,6 +12,7 @@ import { Repository } from 'typeorm'; import { Identity } from '../auth/identity.entity'; import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; +import { User } from '../database/user.entity'; import { NotInDBError, TokenNotValidError, @@ -19,7 +20,6 @@ import { } from '../errors/errors'; import { LoggerModule } from '../logger/logger.module'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { ApiToken } from './api-token.entity'; import { ApiTokenService } from './api-token.service'; diff --git a/backend/src/api-token/api-token.service.ts b/backend/src/api-token/api-token.service.ts index 36fbb0f94..5fbd6e50a 100644 --- a/backend/src/api-token/api-token.service.ts +++ b/backend/src/api-token/api-token.service.ts @@ -10,13 +10,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { createHash, randomBytes, timingSafeEqual } from 'crypto'; import { Repository } from 'typeorm'; +import { User } from '../database/user.entity'; import { NotInDBError, TokenNotValidError, TooManyTokensError, } from '../errors/errors'; import { ConsoleLoggerService } from '../logger/console-logger.service'; -import { User } from '../users/user.entity'; import { bufferToBase64Url } from '../utils/password'; import { ApiToken } from './api-token.entity'; diff --git a/backend/src/api-token/mock-api-token.guard.ts b/backend/src/api-token/mock-api-token.guard.ts index 68e65438b..daf998cdc 100644 --- a/backend/src/api-token/mock-api-token.guard.ts +++ b/backend/src/api-token/mock-api-token.guard.ts @@ -6,7 +6,7 @@ import { ExecutionContext, Injectable } from '@nestjs/common'; import { CompleteRequest } from '../api/utils/request.type'; -import { User } from '../users/user.entity'; +import { User } from '../database/user.entity'; import { UsersService } from '../users/users.service'; @Injectable() diff --git a/backend/src/api/private/alias/alias.controller.ts b/backend/src/api/private/alias/alias.controller.ts index 8a3c54e34..edfb16817 100644 --- a/backend/src/api/private/alias/alias.controller.ts +++ b/backend/src/api/private/alias/alias.controller.ts @@ -20,11 +20,11 @@ import { import { ApiTags } from '@nestjs/swagger'; import { SessionGuard } from '../../../auth/session.guard'; +import { User } from '../../../database/user.entity'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { AliasService } from '../../../notes/alias.service'; import { NotesService } from '../../../notes/notes.service'; import { PermissionsService } from '../../../permissions/permissions.service'; -import { User } from '../../../users/user.entity'; import { UsersService } from '../../../users/users.service'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; diff --git a/backend/src/api/private/auth/local/local.controller.ts b/backend/src/api/private/auth/local/local.controller.ts index 358d85c42..679bc8017 100644 --- a/backend/src/api/private/auth/local/local.controller.ts +++ b/backend/src/api/private/auth/local/local.controller.ts @@ -25,8 +25,8 @@ import { RequestWithSession, SessionGuard, } from '../../../../auth/session.guard'; +import { User } from '../../../../database/user.entity'; import { ConsoleLoggerService } from '../../../../logger/console-logger.service'; -import { User } from '../../../../users/user.entity'; import { UsersService } from '../../../../users/users.service'; import { LoginEnabledGuard } from '../../../utils/login-enabled.guard'; import { OpenApi } from '../../../utils/openapi.decorator'; diff --git a/backend/src/api/private/me/history/history.controller.ts b/backend/src/api/private/me/history/history.controller.ts index c35306a23..5004637da 100644 --- a/backend/src/api/private/me/history/history.controller.ts +++ b/backend/src/api/private/me/history/history.controller.ts @@ -16,13 +16,13 @@ import { import { ApiTags } from '@nestjs/swagger'; import { SessionGuard } from '../../../../auth/session.guard'; +import { User } from '../../../../database/user.entity'; import { HistoryEntryImportListDto } from '../../../../history/history-entry-import.dto'; import { HistoryEntryUpdateDto } from '../../../../history/history-entry-update.dto'; import { HistoryEntryDto } from '../../../../history/history-entry.dto'; import { HistoryService } from '../../../../history/history.service'; import { ConsoleLoggerService } from '../../../../logger/console-logger.service'; import { Note } from '../../../../notes/note.entity'; -import { User } from '../../../../users/user.entity'; import { GetNoteInterceptor } from '../../../utils/get-note.interceptor'; import { OpenApi } from '../../../utils/openapi.decorator'; import { RequestNote } from '../../../utils/request-note.decorator'; diff --git a/backend/src/api/private/me/me.controller.ts b/backend/src/api/private/me/me.controller.ts index a41243e3c..35a9c4da7 100644 --- a/backend/src/api/private/me/me.controller.ts +++ b/backend/src/api/private/me/me.controller.ts @@ -12,6 +12,7 @@ import { Body, Controller, Delete, Get, Put, UseGuards } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { SessionGuard } from '../../../auth/session.guard'; +import { User } from '../../../database/user.entity'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { MediaService } from '../../../media/media.service'; import { User } from '../../../users/user.entity'; diff --git a/backend/src/api/private/media/media.controller.ts b/backend/src/api/private/media/media.controller.ts index 4c36da762..ba7e452b5 100644 --- a/backend/src/api/private/media/media.controller.ts +++ b/backend/src/api/private/media/media.controller.ts @@ -21,6 +21,7 @@ import { ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger'; import { Response } from 'express'; import { SessionGuard } from '../../../auth/session.guard'; +import { User } from '../../../database/user.entity'; import { PermissionError } from '../../../errors/errors'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { MediaService } from '../../../media/media.service'; @@ -30,7 +31,6 @@ import { PermissionsGuard } from '../../../permissions/permissions.guard'; import { PermissionsService } from '../../../permissions/permissions.service'; import { RequirePermission } from '../../../permissions/require-permission.decorator'; import { RequiredPermission } from '../../../permissions/required-permission.enum'; -import { User } from '../../../users/user.entity'; import { NoteHeaderInterceptor } from '../../utils/note-header.interceptor'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestNote } from '../../utils/request-note.decorator'; diff --git a/backend/src/api/private/notes/notes.controller.ts b/backend/src/api/private/notes/notes.controller.ts index f2f52627b..84893f7f9 100644 --- a/backend/src/api/private/notes/notes.controller.ts +++ b/backend/src/api/private/notes/notes.controller.ts @@ -32,6 +32,7 @@ import { import { ApiTags } from '@nestjs/swagger'; import { SessionGuard } from '../../../auth/session.guard'; +import { User } from '../../../database/user.entity'; import { NotInDBError } from '../../../errors/errors'; import { GroupsService } from '../../../groups/groups.service'; import { HistoryService } from '../../../history/history.service'; @@ -44,7 +45,6 @@ import { PermissionsService } from '../../../permissions/permissions.service'; import { RequirePermission } from '../../../permissions/require-permission.decorator'; import { RequiredPermission } from '../../../permissions/required-permission.enum'; import { RevisionsService } from '../../../revisions/revisions.service'; -import { User } from '../../../users/user.entity'; import { UsersService } from '../../../users/users.service'; import { GetNoteInterceptor } from '../../utils/get-note.interceptor'; import { MarkdownBody } from '../../utils/markdown-body.decorator'; diff --git a/backend/src/api/private/tokens/api-tokens.controller.ts b/backend/src/api/private/tokens/api-tokens.controller.ts index a1fad3997..66db25613 100644 --- a/backend/src/api/private/tokens/api-tokens.controller.ts +++ b/backend/src/api/private/tokens/api-tokens.controller.ts @@ -22,8 +22,8 @@ import { ApiTags } from '@nestjs/swagger'; import { ApiTokenService } from '../../../api-token/api-token.service'; import { SessionGuard } from '../../../auth/session.guard'; +import { User } from '../../../database/user.entity'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; -import { User } from '../../../users/user.entity'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; diff --git a/backend/src/api/public/alias/alias.controller.ts b/backend/src/api/public/alias/alias.controller.ts index 0b137ec51..1a7ef3ac8 100644 --- a/backend/src/api/public/alias/alias.controller.ts +++ b/backend/src/api/public/alias/alias.controller.ts @@ -23,11 +23,11 @@ import { import { ApiSecurity, ApiTags } from '@nestjs/swagger'; import { ApiTokenGuard } from '../../../api-token/api-token.guard'; +import { User } from '../../../database/user.entity'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { AliasService } from '../../../notes/alias.service'; import { NotesService } from '../../../notes/notes.service'; import { PermissionsService } from '../../../permissions/permissions.service'; -import { User } from '../../../users/user.entity'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; diff --git a/backend/src/api/public/me/me.controller.ts b/backend/src/api/public/me/me.controller.ts index 5fc4514d5..189adb353 100644 --- a/backend/src/api/public/me/me.controller.ts +++ b/backend/src/api/public/me/me.controller.ts @@ -23,6 +23,7 @@ import { import { ApiSecurity, ApiTags } from '@nestjs/swagger'; import { ApiTokenGuard } from '../../../api-token/api-token.guard'; +import { User } from '../../../database/user.entity'; import { HistoryEntryUpdateDto } from '../../../history/history-entry-update.dto'; import { HistoryEntryDto } from '../../../history/history-entry.dto'; import { HistoryService } from '../../../history/history.service'; @@ -30,7 +31,6 @@ import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { MediaService } from '../../../media/media.service'; import { Note } from '../../../notes/note.entity'; import { NotesService } from '../../../notes/notes.service'; -import { User } from '../../../users/user.entity'; import { UsersService } from '../../../users/users.service'; import { GetNoteInterceptor } from '../../utils/get-note.interceptor'; import { OpenApi } from '../../utils/openapi.decorator'; diff --git a/backend/src/api/public/media/media.controller.ts b/backend/src/api/public/media/media.controller.ts index 8e63cbc21..12ac11d43 100644 --- a/backend/src/api/public/media/media.controller.ts +++ b/backend/src/api/public/media/media.controller.ts @@ -27,6 +27,7 @@ import { import { Response } from 'express'; import { ApiTokenGuard } from '../../../api-token/api-token.guard'; +import { User } from '../../../database/user.entity'; import { PermissionError } from '../../../errors/errors'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { MediaService } from '../../../media/media.service'; @@ -36,7 +37,6 @@ import { PermissionsGuard } from '../../../permissions/permissions.guard'; import { PermissionsService } from '../../../permissions/permissions.service'; import { RequirePermission } from '../../../permissions/require-permission.decorator'; import { RequiredPermission } from '../../../permissions/required-permission.enum'; -import { User } from '../../../users/user.entity'; import { NoteHeaderInterceptor } from '../../utils/note-header.interceptor'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestNote } from '../../utils/request-note.decorator'; diff --git a/backend/src/api/public/notes/notes.controller.ts b/backend/src/api/public/notes/notes.controller.ts index 644e1224f..9ff726c56 100644 --- a/backend/src/api/public/notes/notes.controller.ts +++ b/backend/src/api/public/notes/notes.controller.ts @@ -34,6 +34,7 @@ import { import { ApiSecurity, ApiTags } from '@nestjs/swagger'; import { ApiTokenGuard } from '../../../api-token/api-token.guard'; +import { User } from '../../../database/user.entity'; import { NotInDBError } from '../../../errors/errors'; import { GroupsService } from '../../../groups/groups.service'; import { HistoryService } from '../../../history/history.service'; @@ -46,7 +47,6 @@ import { PermissionsService } from '../../../permissions/permissions.service'; import { RequirePermission } from '../../../permissions/require-permission.decorator'; import { RequiredPermission } from '../../../permissions/required-permission.enum'; import { RevisionsService } from '../../../revisions/revisions.service'; -import { User } from '../../../users/user.entity'; import { UsersService } from '../../../users/users.service'; import { GetNoteInterceptor } from '../../utils/get-note.interceptor'; import { MarkdownBody } from '../../utils/markdown-body.decorator'; diff --git a/backend/src/api/utils/request.type.ts b/backend/src/api/utils/request.type.ts index a5ecfc045..017227f59 100644 --- a/backend/src/api/utils/request.type.ts +++ b/backend/src/api/utils/request.type.ts @@ -5,9 +5,9 @@ */ import { Request } from 'express'; +import { User } from '../../database/user.entity'; import { Note } from '../../notes/note.entity'; import { SessionState } from '../../sessions/session.service'; -import { User } from '../../users/user.entity'; export type CompleteRequest = Request & { user?: User; diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 1aa3f645b..675e64a24 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -8,7 +8,7 @@ import { ConfigModule } from '@nestjs/config'; import { RouterModule, Routes } from '@nestjs/core'; import { EventEmitterModule } from '@nestjs/event-emitter'; import { ScheduleModule } from '@nestjs/schedule'; -import { TypeOrmModule } from '@nestjs/typeorm'; +import { KnexModule } from 'nestjs-knex'; import { ApiTokenModule } from './api-token/api-token.module'; import { PrivateApiModule } from './api/private/private-api.module'; @@ -21,6 +21,7 @@ import cspConfig from './config/csp.config'; import customizationConfig from './config/customization.config'; import databaseConfig, { PostgresDatabaseConfig, + getKnexConfig, } from './config/database.config'; import externalConfig from './config/external-services.config'; import mediaConfig from './config/media.config'; @@ -30,8 +31,8 @@ import { FrontendConfigModule } from './frontend-config/frontend-config.module'; import { FrontendConfigService } from './frontend-config/frontend-config.service'; import { GroupsModule } from './groups/groups.module'; import { HistoryModule } from './history/history.module'; +import { KnexLoggerService } from './logger/knex-logger.service'; import { LoggerModule } from './logger/logger.module'; -import { TypeormLoggerService } from './logger/typeorm-logger.service'; import { MediaRedirectModule } from './media-redirect/media-redirect.module'; import { MediaModule } from './media/media.module'; import { MonitoringModule } from './monitoring/monitoring.module'; @@ -41,7 +42,6 @@ import { WebsocketModule } from './realtime/websocket/websocket.module'; import { RevisionsModule } from './revisions/revisions.module'; import { SessionModule } from './sessions/session.module'; import { UsersModule } from './users/users.module'; -import { detectTsNode } from './utils/detectTsNode'; const routes: Routes = [ { @@ -61,31 +61,23 @@ const routes: Routes = [ @Module({ imports: [ RouterModule.register(routes), - TypeOrmModule.forRootAsync({ + KnexModule.forRootAsync({ imports: [ConfigModule, LoggerModule], - inject: [databaseConfig.KEY, TypeormLoggerService], + inject: [databaseConfig.KEY, KnexLoggerService], useFactory: ( databaseConfig: PostgresDatabaseConfig, - logger: TypeormLoggerService, - ) => { - return { - type: databaseConfig.type, - host: databaseConfig.host, - port: databaseConfig.port, - username: databaseConfig.username, - password: databaseConfig.password, - database: databaseConfig.name, - autoLoadEntities: true, - logging: true, - logger: logger, - migrations: [ - `**/migrations/${databaseConfig.type}-*.${ - detectTsNode() ? 'ts' : 'js' - }`, - ], - migrationsRun: true, - }; - }, + knexLoggerService: KnexLoggerService, + ) => ({ + config: { + ...getKnexConfig(databaseConfig), + log: { + warn: knexLoggerService.warn.bind(knexLoggerService), + error: knexLoggerService.error.bind(knexLoggerService), + deprecate: knexLoggerService.deprecate.bind(knexLoggerService), + debug: knexLoggerService.debug.bind(knexLoggerService), + }, + }, + }), }), ConfigModule.forRoot({ load: [ diff --git a/backend/src/auth/auth.module.ts b/backend/src/auth/auth.module.ts index 2bef49471..fc0f012cf 100644 --- a/backend/src/auth/auth.module.ts +++ b/backend/src/auth/auth.module.ts @@ -6,8 +6,8 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { User } from '../database/user.entity'; import { LoggerModule } from '../logger/logger.module'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { Identity } from './identity.entity'; import { IdentityService } from './identity.service'; diff --git a/backend/src/auth/identity.entity.ts b/backend/src/auth/identity.entity.ts deleted file mode 100644 index 0bdcdf3f5..000000000 --- a/backend/src/auth/identity.entity.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { ProviderType } from '@hedgedoc/commons'; -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { User } from '../users/user.entity'; - -/** - * The identity represents a single way for a user to login. - * A 'user' can have any number of these. - * Each one holds a type (local, github, etc.), if this type can have multiple instances (e.g. gitlab), - * it also saves the name of the instance. Also if this identity shall be the syncSource is saved. - */ -@Entity() -export class Identity { - @PrimaryGeneratedColumn() - id: number; - - /** - * User that this identity corresponds to - */ - @ManyToOne((_) => User, (user) => user.identities, { - onDelete: 'CASCADE', // This deletes the Identity, when the associated User is deleted - }) - user: Promise; - - /** - * The ProviderType of the identity - */ - @Column() - providerType: string; - - /** - * The identifier of the provider. - * Only set if there are multiple providers of that type (e.g. OIDC) - */ - @Column({ - nullable: true, - type: 'text', - }) - providerIdentifier: string | null; - - /** - * When the identity was created. - */ - @CreateDateColumn() - createdAt: Date; - - /** - * When the identity was last updated. - */ - @UpdateDateColumn() - updatedAt: Date; - - /** - * The unique identifier of a user from the login provider - */ - @Column({ - nullable: true, - type: 'text', - }) - providerUserId: string | null; - - /** - * The hash of the password - * Only set when the type of the identity is local - */ - @Column({ - nullable: true, - type: 'text', - }) - passwordHash: string | null; - - public static create( - user: User, - providerType: ProviderType, - providerIdentifier: string | null, - ): Omit { - const newIdentity = new Identity(); - newIdentity.user = Promise.resolve(user); - newIdentity.providerType = providerType; - newIdentity.providerIdentifier = providerIdentifier; - newIdentity.providerUserId = null; - newIdentity.passwordHash = null; - return newIdentity; - } -} diff --git a/backend/src/auth/identity.service.ts b/backend/src/auth/identity.service.ts index 2af021447..ccf4aa6b8 100644 --- a/backend/src/auth/identity.service.ts +++ b/backend/src/auth/identity.service.ts @@ -17,9 +17,9 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { DataSource, Repository } from 'typeorm'; import AuthConfiguration, { AuthConfig } from '../config/auth.config'; +import { User } from '../database/user.entity'; import { NotInDBError } from '../errors/errors'; import { ConsoleLoggerService } from '../logger/console-logger.service'; -import { User } from '../users/user.entity'; import { UsersService } from '../users/users.service'; import { Identity } from './identity.entity'; diff --git a/backend/src/auth/local/local.service.ts b/backend/src/auth/local/local.service.ts index a654a210f..c186023e9 100644 --- a/backend/src/auth/local/local.service.ts +++ b/backend/src/auth/local/local.service.ts @@ -23,13 +23,13 @@ import { import { Repository } from 'typeorm'; import authConfiguration, { AuthConfig } from '../../config/auth.config'; +import { User } from '../../database/user.entity'; import { InvalidCredentialsError, NoLocalIdentityError, PasswordTooWeakError, } from '../../errors/errors'; import { ConsoleLoggerService } from '../../logger/console-logger.service'; -import { User } from '../../users/user.entity'; import { checkPassword, hashPassword } from '../../utils/password'; import { Identity } from '../identity.entity'; import { IdentityService } from '../identity.service'; diff --git a/backend/src/authors/author.entity.ts b/backend/src/authors/author.entity.ts deleted file mode 100644 index 4bb5bcf0d..000000000 --- a/backend/src/authors/author.entity.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - Entity, - ManyToOne, - OneToMany, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { Edit } from '../revisions/edit.entity'; -import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; - -export type AuthorColor = number; - -/** - * The author represents a single user editing a note. - * A 'user' can either be a registered and logged-in user or a browser session identified by its cookie. - * All edits of one user in a note must belong to the same author, so that the same color can be displayed. - */ -@Entity() -export class Author { - @PrimaryGeneratedColumn() - id: number; - - /** - * The id of the color of this author - * The application maps the id to an actual color - */ - @Column({ type: 'int' }) - color: AuthorColor; - - /** - * A list of (browser) sessions this author has - * Only contains sessions for anonymous users, which don't have a user set - */ - @OneToMany(() => Session, (session) => session.author) - sessions: Promise; - - /** - * User that this author corresponds to - * Only set when the user was identified (by a browser session) as a registered user at edit-time - */ - @ManyToOne(() => User, (user) => user.authors, { nullable: true }) - user: Promise; - - /** - * List of edits that this author created - * All edits must belong to the same note - */ - @OneToMany(() => Edit, (edit) => edit.author) - edits: Promise; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - public static create(color: number): Omit { - const newAuthor = new Author(); - newAuthor.color = color; - newAuthor.sessions = Promise.resolve([]); - newAuthor.user = Promise.resolve(null); - newAuthor.edits = Promise.resolve([]); - return newAuthor; - } -} diff --git a/backend/src/config/database-type.enum.ts b/backend/src/config/database-type.enum.ts index 9912332c5..409c434ba 100644 --- a/backend/src/config/database-type.enum.ts +++ b/backend/src/config/database-type.enum.ts @@ -6,7 +6,6 @@ export enum DatabaseType { POSTGRES = 'postgres', - MYSQL = 'mysql', MARIADB = 'mariadb', SQLITE = 'sqlite', } diff --git a/backend/src/config/database.config.ts b/backend/src/config/database.config.ts index 2deccc1b3..d7be8933c 100644 --- a/backend/src/config/database.config.ts +++ b/backend/src/config/database.config.ts @@ -5,6 +5,7 @@ */ import { registerAs } from '@nestjs/config'; import z from 'zod'; +import { Knex } from 'knex'; import { DatabaseType } from './database-type.enum'; import { parseOptionalNumber } from './utils'; @@ -90,3 +91,39 @@ export default registerAs('databaseConfig', () => { } return databaseConfig.data; }); + +export function getKnexConfig(databaseConfig: DatabaseConfig): Knex.Config { + switch (databaseConfig.type) { + case DatabaseType.SQLITE: + return { + client: 'better-sqlite3', + connection: { + filename: databaseConfig.database, + }, + }; + case DatabaseType.POSTGRES: + return { + client: 'pg', + connection: { + host: databaseConfig.host, + port: databaseConfig.port, + user: databaseConfig.username, + database: databaseConfig.database, + password: databaseConfig.password, + // eslint-disable-next-line @typescript-eslint/naming-convention + application_name: 'HedgeDoc', + }, + }; + case DatabaseType.MARIADB: + return { + client: 'mysql', + connection: { + host: databaseConfig.host, + port: databaseConfig.port, + user: databaseConfig.username, + database: databaseConfig.database, + password: databaseConfig.password, + }, + }; + } +} diff --git a/backend/src/database/alias.ts b/backend/src/database/alias.ts new file mode 100644 index 000000000..594a04a9f --- /dev/null +++ b/backend/src/database/alias.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * An alias is a unique identifier for a {@link Note}, making the note accessible under /n/. + * A note can have unlimited user-defined aliases. + * The primary alias is the one used in URLs generated by HedgeDoc. + * For each note, there can only be one primary alias. + */ +export interface Alias { + /** The alias as defined by the user. Is unique. */ + alias: string; + + /** The id of the associated {@link Note}. */ + noteId: number; + + /** Whether the alias is the primary one for the note. */ + isPrimary: boolean; +} diff --git a/backend/src/database/api-token.ts b/backend/src/database/api-token.ts new file mode 100644 index 000000000..52eca966a --- /dev/null +++ b/backend/src/database/api-token.ts @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * An API token can be used to access the public API. + * A token can be created by a {@link User} and is valid until a specified date, at most two years in the future. + * A token has the following format: hd2.. + */ +export interface ApiToken { + /** The id of the token, a short random ASCII string. Is unique */ + id: string; + + /** The {@link User} whose permissions the token has */ + userId: number; + + /** The user-defined label for the token, such as "CLI" */ + label: string; + + /** Hashed version of the token's secret */ + secretHash: string; + + /** Expiry date of the token */ + validUntil: Date; + + /** When the token was last used. When it was never used yet, this field is null */ + lastUsedAt: Date | null; +} diff --git a/backend/src/database/authorship-info.ts b/backend/src/database/authorship-info.ts new file mode 100644 index 000000000..8be52e828 --- /dev/null +++ b/backend/src/database/authorship-info.ts @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +/** + * The AuthorshipInfo holds the information from where to where one {@link User} has changed a {@link Note} + * + * These AuthorshipInfos are combined in a {@link Revision}, which represents one save in the + * {@link Note}'s change history. + */ +export interface AuthorshipInfo { + /** The id of the {@link Revision} this belongs to. */ + revisionId: number; + + /** The id of the author of the edit. */ + authorId: number; + + /** The start position of the change in the note as a positive index. */ + startPos: number; + + /** The end position of the change in the note as a positive index. */ + endPos: number; + + /** The creation datetime of the edit. */ + createdAt: Date; +} diff --git a/backend/src/database/group-user.ts b/backend/src/database/group-user.ts new file mode 100644 index 000000000..71abbccf6 --- /dev/null +++ b/backend/src/database/group-user.ts @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * Maps {@link User}s to {@link Group}s + */ +export interface GroupUser { + /** The id of the {@link Group} a {@link User} is part of */ + groupId: number; + + /** The id of the {@link User} */ + userId: number; +} diff --git a/backend/src/database/group.ts b/backend/src/database/group.ts new file mode 100644 index 000000000..e8080068b --- /dev/null +++ b/backend/src/database/group.ts @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * A group represents one or multiple {@link User}s and can be used for permission management. + * There are special groups that are created by the system and cannot be deleted, these include the set of all + * registered users, as well as all unauthenticated users. + */ +export interface Group { + /** The unique id for internal referencing */ + id: number; + + /** The public identifier of the group (username for the group) */ + name: string; + + /** The display name of the group */ + displayName: string; + + /** Whether the group is one of the special groups */ + isSpecial: boolean; +} diff --git a/backend/src/database/identity.ts b/backend/src/database/identity.ts new file mode 100644 index 000000000..d3afda6a2 --- /dev/null +++ b/backend/src/database/identity.ts @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { ProviderType } from '../auth/provider-type.enum'; + +/** + * An auth identity holds the information how a {@link User} can authenticate themself using a certain auth provider + */ +export interface Identity { + /** The id of the user */ + userId: number; + + /** The type of the auth provider */ + providerType: ProviderType; + + /** The identifier of the auth provider, e.g. gitlab */ + providerIdentifier: string | null; + + /** Timestamp when this identity was created */ + createdAt: Date; + + /** Timestamp when this identity was last updated */ + updatedAt: Date; + + /** The remote id of the user at the auth provider or null for local identities */ + providerUserId: string | null; + + /** The hashed password for local identities or null for other auth providers */ + passwordHash: string | null; +} diff --git a/backend/src/database/knex.types.ts b/backend/src/database/knex.types.ts new file mode 100644 index 000000000..218cf5be6 --- /dev/null +++ b/backend/src/database/knex.types.ts @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { Knex } from 'knex'; + +import { Alias } from './alias'; +import { ApiToken } from './api-token'; +import { AuthorshipInfo } from './authorship-info'; +import { Group } from './group'; +import { GroupUser } from './group-user'; +import { Identity } from './identity'; +import { MediaUpload } from './media-upload'; +import { Note } from './note'; +import { NoteGroupPermission } from './note-group-permission'; +import { NoteUserPermission } from './note-user-permission'; +import { Revision } from './revision'; +import { RevisionTag } from './revision-tag'; +import { User } from './user'; +import { UserPinnedNote } from './user-pinned-note'; + +/* eslint-disable @typescript-eslint/naming-convention */ +declare module 'knex/types/tables' { + interface Tables { + alias_composite: Knex.CompositeTableType< + Alias, + Alias, + Pick + >; + api_token_composite: Knex.CompositeTableType< + ApiToken, + Omit, + Pick + >; + authorship_info_composite: Knex.CompositeTableType< + AuthorshipInfo, + Omit + >; + group_composite: Knex.CompositeTableType< + Group, + Omit, + Pick + >; + group_user_composite: Knex.CompositeTableType; + identity_composite: Knex.CompositeTableType< + Identity, + Omit, + Pick + >; + media_upload_composite: Knex.CompositeTableType< + MediaUpload, + Omit, + Pick + >; + note_composite: Knex.CompositeTableType< + Note, + Omit, + Pick + >; + note_group_permission_composite: Knex.CompositeTableType< + NoteGroupPermission, + NoteGroupPermission, + Pick + >; + note_user_permission_composite: Knex.CompositeTableType< + NoteUserPermission, + NoteUserPermission, + Pick + >; + revision_composite: Knex.CompositeTableType< + Revision, + Omit + >; + revision_tag_composite: Knex.CompositeTableType; + user_composite: Knex.CompositeTableType< + User, + Omit, + Pick + >; + user_pinned_note_composite: Knex.CompositeTableType; + } +} diff --git a/backend/src/database/media-upload.ts b/backend/src/database/media-upload.ts new file mode 100644 index 000000000..d0acd747c --- /dev/null +++ b/backend/src/database/media-upload.ts @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { BackendType } from '../media/backends/backend-type.enum'; + +/** + * A media upload object represents an uploaded file. While the file itself is stored in the configured storage backend, + * the metadata is stored in the database. Uploads are attached to the {@link Note} where they were uploaded, but can be + * detached by deleting the note and setting the option to keep the media files. + */ +export interface MediaUpload { + /** UUID (v7) identifying the media upload. Is public and unique */ + uuid: string; + + /** The id of the attached {@link Note} or null if the media upload was detached from a note */ + noteId: number | null; + + /** The id of the {@link User} who uploaded the media file */ + userId: number; + + /** The name of the uploaded file */ + fileName: string; + + /** The backend where this upload is stored */ + backendType: BackendType; + + /** Additional data required by the backend storage to identify the uploaded file */ + backendData: string | null; + + /** Timestamp when the file was uploaded */ + createdAt: Date; +} diff --git a/backend/src/database/note-group-permission.ts b/backend/src/database/note-group-permission.ts new file mode 100644 index 000000000..89c910ca7 --- /dev/null +++ b/backend/src/database/note-group-permission.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +/** + * Represents a permission for a {@link Note} to be accessed by a {@link Group}. + */ +export interface NoteGroupPermission { + /** The id of the {@link Group} to give the {@link Note} permission to. */ + groupId: number; + + /** The id of the {@link Note} to give the {@link Group} permission to. */ + noteId: number; + + /** Whether the {@link Group} can edit the {@link Note} or not. */ + canEdit: boolean; +} diff --git a/backend/src/database/note-user-permission.ts b/backend/src/database/note-user-permission.ts new file mode 100644 index 000000000..e69ec40d7 --- /dev/null +++ b/backend/src/database/note-user-permission.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +/** + * Represents a permission for a {@link Note} to be accessed by a {@link User}. + */ +export interface NoteUserPermission { + /** The id of the {@link User} to give the {@link Note} permission to. */ + noteId: number; + + /** The id of the {@link Note} to give the {@link User} permission to. */ + userId: number; + + /** Whether the {@link User} can edit the {@link Note} or not. */ + canEdit: boolean; +} diff --git a/backend/src/database/note.ts b/backend/src/database/note.ts new file mode 100644 index 000000000..b0dca9c02 --- /dev/null +++ b/backend/src/database/note.ts @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * Notes are the central part of HedgeDoc. A note is accessed and identified by a list of aliases. + * The note object itself only contains basic metadata about the note. The content is stored in note revisions. + * The permission management is extracted into the note-user and note-group permission tables. + */ +export interface Note { + /** The unique id of the note for internal referencing */ + id: number; + + /** The {@link User} id of the note owner */ + ownerId: string; + + /** The HedgeDoc major version this note was created in. This is used to migrate certain features from HD1 to HD2 */ + version: number; + + /** Timestamp when the note was created */ + createdAt: Date; +} diff --git a/backend/src/database/revision-tag.ts b/backend/src/database/revision-tag.ts new file mode 100644 index 000000000..0c87f27ab --- /dev/null +++ b/backend/src/database/revision-tag.ts @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +/** + * All {@link RevisionTag Tags} that are associated with a {@link Revision}. + */ +export interface RevisionTag { + /** The id of {@link Revision} the {@link RevisionTag Tags} are asspcoated with. */ + revisionId: number; + + /** The {@link RevisionTag Tag} text. */ + tag: string; +} diff --git a/backend/src/database/revision.ts b/backend/src/database/revision.ts new file mode 100644 index 000000000..39c9f5676 --- /dev/null +++ b/backend/src/database/revision.ts @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { NoteType } from '@hedgedoc/commons'; + +/** + * A revision represents the content of a {@link Note} at a specific point in time. + */ +export interface Revision { + /** The unique id of the revision for internal referencing */ + id: number; + + /** The id of the note that this revision belongs to */ + noteId: number; + + /** The changes between this revision and the previous one in patch file format */ + patch: string; + + /** The content of the note at this revision */ + content: string; + + /** The stored Y.js state for realtime editing */ + yjsStateVector: null | ArrayBuffer; + + /** Whether the note is a document or presentation at this revision */ + noteType: NoteType; + + /** The extracted note title from this revision */ + title: string; + + /** The extracted description from this revision */ + description: string; + + /** Timestamp when this revision was created */ + createdAt: Date; +} diff --git a/backend/src/database/user-pinned-note.ts b/backend/src/database/user-pinned-note.ts new file mode 100644 index 000000000..429afbb66 --- /dev/null +++ b/backend/src/database/user-pinned-note.ts @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * A user-pinned-note object represents a {@link Note} that a {@link User} has pinned on their explore page. + * Users can pin any arbitrary amount of notes. + */ +export interface UserPinnedNote { + /** The id of the {@link User} */ + userId: number; + + /** The id of the {@link Note} */ + noteId: number; +} diff --git a/backend/src/database/user.ts b/backend/src/database/user.ts new file mode 100644 index 000000000..653dc47c0 --- /dev/null +++ b/backend/src/database/user.ts @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import type { Username } from '../utils/username'; + +/** + * The user object represents either a registered user in the instance or a guest user. + * + * Registered users have a unique username and a display name. They can authenticate using auth identities + * attached to their account. A registered user can have one or more auth identities. + * + * Guest users are anonymous users that are only identified by a guest UUID. They have a limited set of features + * available and cannot authenticate otherwise than with their UUID. Anonymous note creation or media uploads + * create a guest user, or use an existing one if the UUID is known by the browser. The reason for guest users + * is to allow them to delete their own notes and media files without the need to register an account. + */ +export interface User { + /** The unique id of the user for internal referencing */ + id: number; + + /** The user's chosen username or null if it is a guest user */ + username: Username | null; + + /** The guest user's UUID or null if it is a registered user */ + guestUuid: string | null; + + /** The user's chosen display name */ + displayName: string; + + /** Timestamp when the user was created */ + createdAt: Date; + + /** URL to the user's profile picture if present */ + photoUrl: string | null; + + /** The user's email address if present */ + email: string | null; + + /** The index which author style (e.g. color) should be used for this user */ + authorStyle: number; +} diff --git a/backend/src/groups/group.entity.ts b/backend/src/groups/group.entity.ts deleted file mode 100644 index d4abf660a..000000000 --- a/backend/src/groups/group.entity.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - Entity, - JoinTable, - ManyToMany, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { User } from '../users/user.entity'; - -@Entity() -export class Group { - @PrimaryGeneratedColumn() - id: number; - - @Column({ - unique: true, - }) - name: string; - - @Column() - displayName: string; - - /** - * Is set to denote a special group - * Special groups are used to map the old share settings like "everyone can edit" - * or "logged in users can view" to the group permission system - */ - @Column() - special: boolean; - - @ManyToMany((_) => User, (user) => user.groups, { - eager: true, - }) - @JoinTable() - members: Promise; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - public static create( - name: string, - displayName: string, - special: boolean, - ): Omit { - const newGroup = new Group(); - newGroup.name = name; - newGroup.displayName = displayName; - newGroup.special = special; // this attribute should only be true for the two special groups - newGroup.members = Promise.resolve([]); - return newGroup; - } -} diff --git a/backend/src/history/history-entry.entity.ts b/backend/src/history/history-entry.entity.ts deleted file mode 100644 index 1bd1386b7..000000000 --- a/backend/src/history/history-entry.entity.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - Entity, - Index, - ManyToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; - -@Entity() -@Index(['note', 'user'], { unique: true }) -export class HistoryEntry { - @PrimaryGeneratedColumn() - id: number; - - @ManyToOne((_) => User, (user) => user.historyEntries, { - onDelete: 'CASCADE', - orphanedRowAction: 'delete', // This ensures the row of the history entry is deleted when no user references it anymore - }) - user: Promise; - - @ManyToOne((_) => Note, (note) => note.historyEntries, { - onDelete: 'CASCADE', - orphanedRowAction: 'delete', // This ensures the row of the history entry is deleted when no note references it anymore - }) - note: Promise; - - @Column() - pinStatus: boolean; - - @UpdateDateColumn() - updatedAt: Date; - - /** - * Create a history entry - * @param user the user the history entry is associated with - * @param note the note the history entry is associated with - * @param [pinStatus=false] if the history entry should be pinned - */ - public static create( - user: User, - note: Note, - pinStatus = false, - ): Omit { - const newHistoryEntry = new HistoryEntry(); - newHistoryEntry.user = Promise.resolve(user); - newHistoryEntry.note = Promise.resolve(note); - newHistoryEntry.pinStatus = pinStatus; - return newHistoryEntry; - } -} diff --git a/backend/src/history/history.service.spec.ts b/backend/src/history/history.service.spec.ts index 5ca219d94..adfde2b9b 100644 --- a/backend/src/history/history.service.spec.ts +++ b/backend/src/history/history.service.spec.ts @@ -18,6 +18,7 @@ import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; import databaseConfigMock from '../config/mock/database.config.mock'; import noteConfigMock from '../config/mock/note.config.mock'; +import { User } from '../database/user.entity'; import { NotInDBError } from '../errors/errors'; import { eventModuleConfig } from '../events'; import { Group } from '../groups/group.entity'; @@ -33,7 +34,6 @@ import { Revision } from '../revisions/revision.entity'; import { RevisionsModule } from '../revisions/revisions.module'; import { RevisionsService } from '../revisions/revisions.service'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { mockSelectQueryBuilderInRepo } from '../utils/test-utils/mockSelectQueryBuilder'; import { HistoryEntryImportDto } from './history-entry-import.dto'; diff --git a/backend/src/history/history.service.ts b/backend/src/history/history.service.ts index 93356e807..76c45b7ef 100644 --- a/backend/src/history/history.service.ts +++ b/backend/src/history/history.service.ts @@ -7,12 +7,12 @@ import { Injectable } from '@nestjs/common'; import { InjectConnection, InjectRepository } from '@nestjs/typeorm'; import { Connection, Repository } from 'typeorm'; +import { User } from '../database/user.entity'; import { NotInDBError } from '../errors/errors'; import { ConsoleLoggerService } from '../logger/console-logger.service'; import { Note } from '../notes/note.entity'; import { NotesService } from '../notes/notes.service'; import { RevisionsService } from '../revisions/revisions.service'; -import { User } from '../users/user.entity'; import { UsersService } from '../users/users.service'; import { HistoryEntryImportDto } from './history-entry-import.dto'; import { HistoryEntryUpdateDto } from './history-entry-update.dto'; diff --git a/backend/src/history/utils.spec.ts b/backend/src/history/utils.spec.ts index d65fc617b..14cdd8545 100644 --- a/backend/src/history/utils.spec.ts +++ b/backend/src/history/utils.spec.ts @@ -3,9 +3,9 @@ * * SPDX-License-Identifier: AGPL-3.0-only */ +import { User } from '../database/user.entity'; import { Alias } from '../notes/alias.entity'; import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; import { HistoryEntry } from './history-entry.entity'; import { getIdentifier } from './utils'; diff --git a/backend/src/logger/knex-logger.service.ts b/backend/src/logger/knex-logger.service.ts new file mode 100644 index 000000000..1986bb886 --- /dev/null +++ b/backend/src/logger/knex-logger.service.ts @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + * + * The code in this class is based on: + * https://github.com/typeorm/typeorm/blob/master/src/logger/AdvancedConsoleLogger.ts + */ +import { Injectable } from '@nestjs/common'; + +import { ConsoleLoggerService } from './console-logger.service'; + +@Injectable() +export class KnexLoggerService { + constructor(private readonly logger: ConsoleLoggerService) { + this.logger.setContext('Knex'); + } + + warn(message: string): void { + this.logger.warn(message); + } + + error(message: string): void { + this.logger.error(message); + } + + deprecate(message: string): void { + this.logger.warn(message); + } + + debug(message: string): void { + this.logger.debug(message); + } +} diff --git a/backend/src/logger/logger.module.ts b/backend/src/logger/logger.module.ts index d4c5caab2..231226f41 100644 --- a/backend/src/logger/logger.module.ts +++ b/backend/src/logger/logger.module.ts @@ -6,10 +6,10 @@ import { Module } from '@nestjs/common'; import { ConsoleLoggerService } from './console-logger.service'; -import { TypeormLoggerService } from './typeorm-logger.service'; +import { KnexLoggerService } from './knex-logger.service'; @Module({ - providers: [ConsoleLoggerService, TypeormLoggerService], - exports: [ConsoleLoggerService, TypeormLoggerService], + providers: [ConsoleLoggerService, KnexLoggerService], + exports: [ConsoleLoggerService, KnexLoggerService], }) export class LoggerModule {} diff --git a/backend/src/logger/typeorm-logger.service.ts b/backend/src/logger/typeorm-logger.service.ts deleted file mode 100644 index 8f075f336..000000000 --- a/backend/src/logger/typeorm-logger.service.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - * - * The code in this class is based on: - * https://github.com/typeorm/typeorm/blob/master/src/logger/AdvancedConsoleLogger.ts - */ -import { Injectable } from '@nestjs/common'; -import { Logger, QueryRunner } from 'typeorm'; -import { PlatformTools } from 'typeorm/platform/PlatformTools'; - -import { ConsoleLoggerService } from './console-logger.service'; - -@Injectable() -export class TypeormLoggerService implements Logger { - constructor(private readonly logger: ConsoleLoggerService) { - this.logger.setContext('TypeORM'); - this.logger.setSkipColor(true); - } - - log(level: 'log' | 'info' | 'warn', message: unknown, _?: QueryRunner): void { - switch (level) { - case 'log': - case 'info': - this.logger.log(message); - break; - case 'warn': - this.logger.warn(message); - } - } - - logMigration(message: string, _?: QueryRunner): void { - // eslint-disable-next-line local-rules/correct-logger-context - this.logger.log(message, 'migration'); - } - - logQuery(query: string, parameters?: unknown[], _?: QueryRunner): void { - const sql = - query + - (parameters && parameters.length - ? ' -- PARAMETERS: ' + this.stringifyParams(parameters) - : ''); - // eslint-disable-next-line local-rules/correct-logger-context - this.logger.debug(PlatformTools.highlightSql(sql), 'query'); - } - - logQueryError( - error: string | Error, - query: string, - parameters?: unknown[], - _?: QueryRunner, - ): void { - const sql = - query + - (parameters && parameters.length - ? ` -- PARAMETERS: ${this.stringifyParams(parameters)}` - : ''); - this.logger.debug(PlatformTools.highlightSql(sql)); - // eslint-disable-next-line local-rules/correct-logger-context - this.logger.debug(error.toString(), 'queryError'); - } - - logQuerySlow( - time: number, - query: string, - parameters?: unknown[], - _?: QueryRunner, - ): void { - const sql = - query + - (parameters && parameters.length - ? ` -- PARAMETERS: ${this.stringifyParams(parameters)}` - : ''); - /* eslint-disable local-rules/correct-logger-context */ - this.logger.warn(PlatformTools.highlightSql(sql), 'querySlow'); - this.logger.warn(`execution time: ${time}`, 'querySlow'); - /* eslint-enable local-rules/correct-logger-context */ - } - - logSchemaBuild(message: string, _?: QueryRunner): void { - // eslint-disable-next-line local-rules/correct-logger-context - this.logger.debug(message, 'schemaBuild'); - } - - /** - * Converts parameters to a string. - * Sometimes parameters can have circular objects and therefore we are handle this case too. - */ - protected stringifyParams(parameters: unknown[]): string { - try { - return JSON.stringify(parameters); - } catch (error) { - // most probably circular objects in parameters - return parameters.toString(); - } - } -} diff --git a/backend/src/media/media-upload.entity.ts b/backend/src/media/media-upload.entity.ts deleted file mode 100644 index bf8a91baf..000000000 --- a/backend/src/media/media-upload.entity.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - PrimaryColumn, -} from 'typeorm'; - -import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; -import { BackendType } from './backends/backend-type.enum'; - -@Entity() -export class MediaUpload { - /** The unique identifier of a media upload */ - @PrimaryColumn() - uuid: string; - - /** - * The note where a media file was uploaded, required for the media browser in the note editor. - * Can be set to null after creation when the note was deleted without the associated uploads - */ - @ManyToOne((_) => Note, (note) => note.mediaUploads, { - nullable: true, - }) - note: Promise; - - /** The user who uploaded the media file or {@code null} if uploaded by a guest user */ - @ManyToOne((_) => User, (user) => user.mediaUploads, { - nullable: true, - }) - user: Promise; - - /** The original filename of the media upload */ - @Column() - fileName: string; - - /** The backend type where this upload is stored */ - @Column({ - nullable: false, - }) - backendType: string; - - /** - * Additional data, depending on the backend type, serialized as JSON. - * This can include for example required additional identifiers for retrieving the file from the backend or to - * delete the file afterward again. - */ - @Column({ - nullable: true, - type: 'text', - }) - backendData: string | null; - - /** The date when the upload was created */ - @CreateDateColumn() - createdAt: Date; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - /** - * Create a new media upload entity - * - * @param uuid the unique identifier of the upload - * @param fileName the original filename of the uploaded file - * @param note the note the upload should be associated with. This is required despite the fact the note field is optional, because it's possible to delete a note without also deleting the associated media uploads, but a note is required for the initial creation. - * @param user the user that owns the upload - * @param backendType on which type of media backend the upload is saved - * @param backendData the backend data returned by the media backend - */ - public static create( - uuid: string, - fileName: string, - note: Note, - user: User | null, - backendType: BackendType, - backendData: string | null, - ): Omit { - const upload = new MediaUpload(); - upload.uuid = uuid; - upload.fileName = fileName; - upload.note = Promise.resolve(note); - upload.user = Promise.resolve(user); - upload.backendType = backendType; - upload.backendData = backendData; - return upload; - } -} diff --git a/backend/src/media/media.service.spec.ts b/backend/src/media/media.service.spec.ts index c04c4e373..f5cfc52ce 100644 --- a/backend/src/media/media.service.spec.ts +++ b/backend/src/media/media.service.spec.ts @@ -18,6 +18,7 @@ import authConfigMock from '../config/mock/auth.config.mock'; import databaseConfigMock from '../config/mock/database.config.mock'; import mediaConfigMock from '../config/mock/media.config.mock'; import noteConfigMock from '../config/mock/note.config.mock'; +import { User } from '../database/user.entity'; import { ClientError, NotInDBError } from '../errors/errors'; import { eventModuleConfig } from '../events'; import { Group } from '../groups/group.entity'; @@ -31,7 +32,6 @@ import { NoteUserPermission } from '../permissions/note-user-permission.entity'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { BackendType } from './backends/backend-type.enum'; import { FilesystemBackend } from './backends/filesystem-backend'; diff --git a/backend/src/media/media.service.ts b/backend/src/media/media.service.ts index 0a8396a2a..0485f3913 100644 --- a/backend/src/media/media.service.ts +++ b/backend/src/media/media.service.ts @@ -12,10 +12,10 @@ import { Repository } from 'typeorm'; import { v7 as uuidV7 } from 'uuid'; import mediaConfiguration, { MediaConfig } from '../config/media.config'; +import { User } from '../database/user.entity'; import { ClientError, NotInDBError } from '../errors/errors'; import { ConsoleLoggerService } from '../logger/console-logger.service'; import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; import { AzureBackend } from './backends/azure-backend'; import { BackendType } from './backends/backend-type.enum'; import { FilesystemBackend } from './backends/filesystem-backend'; diff --git a/backend/src/migrations/mariadb-1726271650566-init.ts b/backend/src/migrations/mariadb-1726271650566-init.ts deleted file mode 100644 index dacaad3d2..000000000 --- a/backend/src/migrations/mariadb-1726271650566-init.ts +++ /dev/null @@ -1,268 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class Init1726271650566 implements MigrationInterface { - name = 'Init1726271650566'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE \`api_token\` (\`id\` int NOT NULL AUTO_INCREMENT, \`keyId\` varchar(255) NOT NULL, \`label\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`hash\` varchar(255) NOT NULL, \`validUntil\` datetime NOT NULL, \`lastUsedAt\` date NULL, \`userId\` int NULL, UNIQUE INDEX \`IDX_3e254e2eb542a65da7c405d068\` (\`keyId\`), UNIQUE INDEX \`IDX_60221392192b32c7560c128a6f\` (\`hash\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`history_entry\` (\`id\` int NOT NULL AUTO_INCREMENT, \`pinStatus\` tinyint NOT NULL, \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`userId\` int NULL, \`noteId\` int NULL, UNIQUE INDEX \`IDX_928dd947355b0837366470a916\` (\`noteId\`, \`userId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`media_upload\` (\`uuid\` varchar(255) NOT NULL, \`fileName\` varchar(255) NOT NULL, \`backendType\` varchar(255) NOT NULL, \`backendData\` text NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`noteId\` int NULL, \`userId\` int NULL, PRIMARY KEY (\`uuid\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`group\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(255) NOT NULL, \`displayName\` varchar(255) NOT NULL, \`special\` tinyint NOT NULL, UNIQUE INDEX \`IDX_8a45300fd825918f3b40195fbd\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`note_group_permission\` (\`id\` int NOT NULL AUTO_INCREMENT, \`canEdit\` tinyint NOT NULL, \`groupId\` int NULL, \`noteId\` int NULL, UNIQUE INDEX \`IDX_ee1744842a9ef3ffbc05a7016a\` (\`groupId\`, \`noteId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`note_user_permission\` (\`id\` int NOT NULL AUTO_INCREMENT, \`canEdit\` tinyint NOT NULL, \`userId\` int NULL, \`noteId\` int NULL, UNIQUE INDEX \`IDX_5a3e91233d8878f98f5ad86b71\` (\`userId\`, \`noteId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`alias\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(255) NOT NULL, \`primary\` tinyint NULL COMMENT 'This field tells you if this is the primary alias of the note. If this field is null, that means this alias is not primary.', \`noteId\` int NULL, UNIQUE INDEX \`IDX_89f27e45cc5c1e43abd9132c9b\` (\`name\`), UNIQUE INDEX \`Only one primary alias per note\` (\`noteId\`, \`primary\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`note\` (\`id\` int NOT NULL AUTO_INCREMENT, \`publicId\` text NOT NULL, \`viewCount\` int NOT NULL DEFAULT '0', \`version\` int NOT NULL DEFAULT '2', \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`ownerId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`tag\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`revision\` (\`id\` int NOT NULL AUTO_INCREMENT, \`patch\` text NOT NULL, \`title\` text NOT NULL, \`description\` text NOT NULL, \`content\` text NOT NULL, \`length\` int NOT NULL, \`yjsStateVector\` text NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`noteId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`edit\` (\`id\` int NOT NULL AUTO_INCREMENT, \`startPos\` int NOT NULL, \`endPos\` int NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`authorId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`session\` (\`id\` varchar(255) NOT NULL, \`expiredAt\` bigint NOT NULL, \`json\` text NOT NULL, \`destroyedAt\` datetime(6) NULL, \`authorId\` int NULL, INDEX \`IDX_28c5d1d16da7908c97c9bc2f74\` (\`expiredAt\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`author\` (\`id\` int NOT NULL AUTO_INCREMENT, \`color\` int NOT NULL, \`userId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`user\` (\`id\` int NOT NULL AUTO_INCREMENT, \`username\` varchar(255) NOT NULL, \`displayName\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`photo\` text NULL, \`email\` text NULL, UNIQUE INDEX \`IDX_78a916df40e02a9deb1c4b75ed\` (\`username\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`identity\` (\`id\` int NOT NULL AUTO_INCREMENT, \`providerType\` varchar(255) NOT NULL, \`providerIdentifier\` text NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`providerUserId\` text NULL, \`passwordHash\` text NULL, \`userId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`group_members_user\` (\`groupId\` int NOT NULL, \`userId\` int NOT NULL, INDEX \`IDX_bfa303089d367a2e3c02b002b8\` (\`groupId\`), INDEX \`IDX_427107c650638bcb2f1e167d2e\` (\`userId\`), PRIMARY KEY (\`groupId\`, \`userId\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`revision_tags_tag\` (\`revisionId\` int NOT NULL, \`tagId\` int NOT NULL, INDEX \`IDX_3382f45eefeb40f91e45cfd418\` (\`revisionId\`), INDEX \`IDX_19dbafe2a8b456c0ef40858d49\` (\`tagId\`), PRIMARY KEY (\`revisionId\`, \`tagId\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `CREATE TABLE \`revision_edits_edit\` (\`revisionId\` int NOT NULL, \`editId\` int NOT NULL, INDEX \`IDX_52c6a61e1a646768391c7854fe\` (\`revisionId\`), INDEX \`IDX_470886feb50e30114e39c42698\` (\`editId\`), PRIMARY KEY (\`revisionId\`, \`editId\`)) ENGINE=InnoDB`, - ); - await queryRunner.query( - `ALTER TABLE \`api_token\` ADD CONSTRAINT \`FK_cbfc4e2b85b78207afb0b2d7fbc\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`history_entry\` ADD CONSTRAINT \`FK_42b8ae461cb58747a24340e6c64\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`history_entry\` ADD CONSTRAINT \`FK_8f3595373fc9f6a32f126270422\` FOREIGN KEY (\`noteId\`) REFERENCES \`note\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`media_upload\` ADD CONSTRAINT \`FK_edba6d4e0f3bcf6605772f0af6b\` FOREIGN KEY (\`noteId\`) REFERENCES \`note\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`media_upload\` ADD CONSTRAINT \`FK_73ce66b082df1df2003e305e9ac\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`note_group_permission\` ADD CONSTRAINT \`FK_743ea3d9e0e26d7cbb9c174e56b\` FOREIGN KEY (\`groupId\`) REFERENCES \`group\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`note_group_permission\` ADD CONSTRAINT \`FK_fd5c9329d8b45cb160676f8d8c1\` FOREIGN KEY (\`noteId\`) REFERENCES \`note\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`note_user_permission\` ADD CONSTRAINT \`FK_03cea81e07bab8864de026d517d\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`note_user_permission\` ADD CONSTRAINT \`FK_bc1ca3a87a9d662350d281a7f16\` FOREIGN KEY (\`noteId\`) REFERENCES \`note\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`alias\` ADD CONSTRAINT \`FK_63012a303e6ca53144a8b7b64b0\` FOREIGN KEY (\`noteId\`) REFERENCES \`note\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`note\` ADD CONSTRAINT \`FK_b09836eba01a8653c0628a78af8\` FOREIGN KEY (\`ownerId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`revision\` ADD CONSTRAINT \`FK_8ac498c7c70de43d01b94fe7905\` FOREIGN KEY (\`noteId\`) REFERENCES \`note\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`edit\` ADD CONSTRAINT \`FK_bbab22ed1a0e243b28623f4f48a\` FOREIGN KEY (\`authorId\`) REFERENCES \`author\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`session\` ADD CONSTRAINT \`FK_e5da4837ed9d236532b3215a84e\` FOREIGN KEY (\`authorId\`) REFERENCES \`author\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`author\` ADD CONSTRAINT \`FK_645811deaaaa772f9e6c2a4b927\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`identity\` ADD CONSTRAINT \`FK_12915039d2868ab654567bf5181\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`group_members_user\` ADD CONSTRAINT \`FK_bfa303089d367a2e3c02b002b8f\` FOREIGN KEY (\`groupId\`) REFERENCES \`group\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE \`group_members_user\` ADD CONSTRAINT \`FK_427107c650638bcb2f1e167d2e5\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`revision_tags_tag\` ADD CONSTRAINT \`FK_3382f45eefeb40f91e45cfd4180\` FOREIGN KEY (\`revisionId\`) REFERENCES \`revision\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE \`revision_tags_tag\` ADD CONSTRAINT \`FK_19dbafe2a8b456c0ef40858d49f\` FOREIGN KEY (\`tagId\`) REFERENCES \`tag\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE \`revision_edits_edit\` ADD CONSTRAINT \`FK_52c6a61e1a646768391c7854feb\` FOREIGN KEY (\`revisionId\`) REFERENCES \`revision\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE \`revision_edits_edit\` ADD CONSTRAINT \`FK_470886feb50e30114e39c426987\` FOREIGN KEY (\`editId\`) REFERENCES \`edit\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE \`revision_edits_edit\` DROP FOREIGN KEY \`FK_470886feb50e30114e39c426987\``, - ); - await queryRunner.query( - `ALTER TABLE \`revision_edits_edit\` DROP FOREIGN KEY \`FK_52c6a61e1a646768391c7854feb\``, - ); - await queryRunner.query( - `ALTER TABLE \`revision_tags_tag\` DROP FOREIGN KEY \`FK_19dbafe2a8b456c0ef40858d49f\``, - ); - await queryRunner.query( - `ALTER TABLE \`revision_tags_tag\` DROP FOREIGN KEY \`FK_3382f45eefeb40f91e45cfd4180\``, - ); - await queryRunner.query( - `ALTER TABLE \`group_members_user\` DROP FOREIGN KEY \`FK_427107c650638bcb2f1e167d2e5\``, - ); - await queryRunner.query( - `ALTER TABLE \`group_members_user\` DROP FOREIGN KEY \`FK_bfa303089d367a2e3c02b002b8f\``, - ); - await queryRunner.query( - `ALTER TABLE \`identity\` DROP FOREIGN KEY \`FK_12915039d2868ab654567bf5181\``, - ); - await queryRunner.query( - `ALTER TABLE \`author\` DROP FOREIGN KEY \`FK_645811deaaaa772f9e6c2a4b927\``, - ); - await queryRunner.query( - `ALTER TABLE \`session\` DROP FOREIGN KEY \`FK_e5da4837ed9d236532b3215a84e\``, - ); - await queryRunner.query( - `ALTER TABLE \`edit\` DROP FOREIGN KEY \`FK_bbab22ed1a0e243b28623f4f48a\``, - ); - await queryRunner.query( - `ALTER TABLE \`revision\` DROP FOREIGN KEY \`FK_8ac498c7c70de43d01b94fe7905\``, - ); - await queryRunner.query( - `ALTER TABLE \`note\` DROP FOREIGN KEY \`FK_b09836eba01a8653c0628a78af8\``, - ); - await queryRunner.query( - `ALTER TABLE \`alias\` DROP FOREIGN KEY \`FK_63012a303e6ca53144a8b7b64b0\``, - ); - await queryRunner.query( - `ALTER TABLE \`note_user_permission\` DROP FOREIGN KEY \`FK_bc1ca3a87a9d662350d281a7f16\``, - ); - await queryRunner.query( - `ALTER TABLE \`note_user_permission\` DROP FOREIGN KEY \`FK_03cea81e07bab8864de026d517d\``, - ); - await queryRunner.query( - `ALTER TABLE \`note_group_permission\` DROP FOREIGN KEY \`FK_fd5c9329d8b45cb160676f8d8c1\``, - ); - await queryRunner.query( - `ALTER TABLE \`note_group_permission\` DROP FOREIGN KEY \`FK_743ea3d9e0e26d7cbb9c174e56b\``, - ); - await queryRunner.query( - `ALTER TABLE \`media_upload\` DROP FOREIGN KEY \`FK_73ce66b082df1df2003e305e9ac\``, - ); - await queryRunner.query( - `ALTER TABLE \`media_upload\` DROP FOREIGN KEY \`FK_edba6d4e0f3bcf6605772f0af6b\``, - ); - await queryRunner.query( - `ALTER TABLE \`history_entry\` DROP FOREIGN KEY \`FK_8f3595373fc9f6a32f126270422\``, - ); - await queryRunner.query( - `ALTER TABLE \`history_entry\` DROP FOREIGN KEY \`FK_42b8ae461cb58747a24340e6c64\``, - ); - await queryRunner.query( - `ALTER TABLE \`api_token\` DROP FOREIGN KEY \`FK_cbfc4e2b85b78207afb0b2d7fbc\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_470886feb50e30114e39c42698\` ON \`revision_edits_edit\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_52c6a61e1a646768391c7854fe\` ON \`revision_edits_edit\``, - ); - await queryRunner.query(`DROP TABLE \`revision_edits_edit\``); - await queryRunner.query( - `DROP INDEX \`IDX_19dbafe2a8b456c0ef40858d49\` ON \`revision_tags_tag\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_3382f45eefeb40f91e45cfd418\` ON \`revision_tags_tag\``, - ); - await queryRunner.query(`DROP TABLE \`revision_tags_tag\``); - await queryRunner.query( - `DROP INDEX \`IDX_427107c650638bcb2f1e167d2e\` ON \`group_members_user\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_bfa303089d367a2e3c02b002b8\` ON \`group_members_user\``, - ); - await queryRunner.query(`DROP TABLE \`group_members_user\``); - await queryRunner.query(`DROP TABLE \`identity\``); - await queryRunner.query( - `DROP INDEX \`IDX_78a916df40e02a9deb1c4b75ed\` ON \`user\``, - ); - await queryRunner.query(`DROP TABLE \`user\``); - await queryRunner.query(`DROP TABLE \`author\``); - await queryRunner.query( - `DROP INDEX \`IDX_28c5d1d16da7908c97c9bc2f74\` ON \`session\``, - ); - await queryRunner.query(`DROP TABLE \`session\``); - await queryRunner.query(`DROP TABLE \`edit\``); - await queryRunner.query(`DROP TABLE \`revision\``); - await queryRunner.query(`DROP TABLE \`tag\``); - await queryRunner.query(`DROP TABLE \`note\``); - await queryRunner.query( - `DROP INDEX \`Only one primary alias per note\` ON \`alias\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_89f27e45cc5c1e43abd9132c9b\` ON \`alias\``, - ); - await queryRunner.query(`DROP TABLE \`alias\``); - await queryRunner.query( - `DROP INDEX \`IDX_5a3e91233d8878f98f5ad86b71\` ON \`note_user_permission\``, - ); - await queryRunner.query(`DROP TABLE \`note_user_permission\``); - await queryRunner.query( - `DROP INDEX \`IDX_ee1744842a9ef3ffbc05a7016a\` ON \`note_group_permission\``, - ); - await queryRunner.query(`DROP TABLE \`note_group_permission\``); - await queryRunner.query( - `DROP INDEX \`IDX_8a45300fd825918f3b40195fbd\` ON \`group\``, - ); - await queryRunner.query(`DROP TABLE \`group\``); - await queryRunner.query(`DROP TABLE \`media_upload\``); - await queryRunner.query( - `DROP INDEX \`IDX_928dd947355b0837366470a916\` ON \`history_entry\``, - ); - await queryRunner.query(`DROP TABLE \`history_entry\``); - await queryRunner.query( - `DROP INDEX \`IDX_60221392192b32c7560c128a6f\` ON \`api_token\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_3e254e2eb542a65da7c405d068\` ON \`api_token\``, - ); - await queryRunner.query(`DROP TABLE \`api_token\``); - } -} diff --git a/backend/src/migrations/postgres-1726271794336-init.ts b/backend/src/migrations/postgres-1726271794336-init.ts deleted file mode 100644 index 8541dccec..000000000 --- a/backend/src/migrations/postgres-1726271794336-init.ts +++ /dev/null @@ -1,280 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class Init1726271794336 implements MigrationInterface { - name = 'Init1726271794336'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "api_token" ("id" SERIAL NOT NULL, "keyId" character varying NOT NULL, "label" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "hash" character varying NOT NULL, "validUntil" TIMESTAMP NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_3e254e2eb542a65da7c405d0683" UNIQUE ("keyId"), CONSTRAINT "UQ_60221392192b32c7560c128a6fa" UNIQUE ("hash"), CONSTRAINT "PK_d862311c568d175c26f41bc6f98" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "history_entry" ("id" SERIAL NOT NULL, "pinStatus" boolean NOT NULL, "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "userId" integer, "noteId" integer, CONSTRAINT "PK_b65bd95b0d2929668589d57b97a" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_928dd947355b0837366470a916" ON "history_entry" ("noteId", "userId") `, - ); - await queryRunner.query( - `CREATE TABLE "media_upload" ("uuid" character varying NOT NULL, "fileName" character varying NOT NULL, "backendType" character varying NOT NULL, "backendData" text, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "noteId" integer, "userId" integer, CONSTRAINT "PK_573c2a4f2a8f8382f2a8758444e" PRIMARY KEY ("uuid"))`, - ); - await queryRunner.query( - `CREATE TABLE "group" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, "displayName" character varying NOT NULL, "special" boolean NOT NULL, CONSTRAINT "UQ_8a45300fd825918f3b40195fbdc" UNIQUE ("name"), CONSTRAINT "PK_256aa0fda9b1de1a73ee0b7106b" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "note_group_permission" ("id" SERIAL NOT NULL, "canEdit" boolean NOT NULL, "groupId" integer, "noteId" integer, CONSTRAINT "PK_6327989190949e6a55d02a080c3" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_ee1744842a9ef3ffbc05a7016a" ON "note_group_permission" ("groupId", "noteId") `, - ); - await queryRunner.query( - `CREATE TABLE "note_user_permission" ("id" SERIAL NOT NULL, "canEdit" boolean NOT NULL, "userId" integer, "noteId" integer, CONSTRAINT "PK_672af1e0c89837f0aa390d34b8d" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_5a3e91233d8878f98f5ad86b71" ON "note_user_permission" ("userId", "noteId") `, - ); - await queryRunner.query( - `CREATE TABLE "alias" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, "primary" boolean, "noteId" integer, CONSTRAINT "UQ_89f27e45cc5c1e43abd9132c9b9" UNIQUE ("name"), CONSTRAINT "Only one primary alias per note" UNIQUE ("noteId", "primary"), CONSTRAINT "PK_b1848d04b41d10a5712fc2e673c" PRIMARY KEY ("id")); COMMENT ON COLUMN "alias"."primary" IS 'This field tells you if this is the primary alias of the note. If this field is null, that means this alias is not primary.'`, - ); - await queryRunner.query( - `CREATE TABLE "note" ("id" SERIAL NOT NULL, "publicId" text NOT NULL, "viewCount" integer NOT NULL DEFAULT '0', "version" integer NOT NULL DEFAULT '2', "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "ownerId" integer, CONSTRAINT "PK_96d0c172a4fba276b1bbed43058" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "tag" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_8e4052373c579afc1471f526760" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "revision" ("id" SERIAL NOT NULL, "patch" text NOT NULL, "title" text NOT NULL, "description" text NOT NULL, "content" text NOT NULL, "length" integer NOT NULL, "yjsStateVector" text, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "noteId" integer, CONSTRAINT "PK_f4767cdf0c0e78041514e5a94be" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "edit" ("id" SERIAL NOT NULL, "startPos" integer NOT NULL, "endPos" integer NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "authorId" integer, CONSTRAINT "PK_062a4b68154c101205e4595810d" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "session" ("id" character varying(255) NOT NULL, "expiredAt" bigint NOT NULL, "json" text NOT NULL, "destroyedAt" TIMESTAMP, "authorId" integer, CONSTRAINT "PK_f55da76ac1c3ac420f444d2ff11" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_28c5d1d16da7908c97c9bc2f74" ON "session" ("expiredAt") `, - ); - await queryRunner.query( - `CREATE TABLE "author" ("id" SERIAL NOT NULL, "color" integer NOT NULL, "userId" integer, CONSTRAINT "PK_5a0e79799d372fe56f2f3fa6871" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "user" ("id" SERIAL NOT NULL, "username" character varying NOT NULL, "displayName" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "photo" text, "email" text, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "identity" ("id" SERIAL NOT NULL, "providerType" character varying NOT NULL, "providerIdentifier" text, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "providerUserId" text, "passwordHash" text, "userId" integer, CONSTRAINT "PK_ff16a44186b286d5e626178f726" PRIMARY KEY ("id"))`, - ); - await queryRunner.query( - `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "PK_7170c9a27e7b823d391d9e11f2e" PRIMARY KEY ("groupId", "userId"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, - ); - await queryRunner.query( - `CREATE TABLE "revision_tags_tag" ("revisionId" integer NOT NULL, "tagId" integer NOT NULL, CONSTRAINT "PK_006354d3ecad6cb1e606320647b" PRIMARY KEY ("revisionId", "tagId"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_3382f45eefeb40f91e45cfd418" ON "revision_tags_tag" ("revisionId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_19dbafe2a8b456c0ef40858d49" ON "revision_tags_tag" ("tagId") `, - ); - await queryRunner.query( - `CREATE TABLE "revision_edits_edit" ("revisionId" integer NOT NULL, "editId" integer NOT NULL, CONSTRAINT "PK_2651ab66ea1c428e844a80d81ed" PRIMARY KEY ("revisionId", "editId"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_52c6a61e1a646768391c7854fe" ON "revision_edits_edit" ("revisionId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, - ); - await queryRunner.query( - `ALTER TABLE "api_token" ADD CONSTRAINT "FK_cbfc4e2b85b78207afb0b2d7fbc" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "history_entry" ADD CONSTRAINT "FK_42b8ae461cb58747a24340e6c64" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "history_entry" ADD CONSTRAINT "FK_8f3595373fc9f6a32f126270422" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "media_upload" ADD CONSTRAINT "FK_edba6d4e0f3bcf6605772f0af6b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "media_upload" ADD CONSTRAINT "FK_73ce66b082df1df2003e305e9ac" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "note_group_permission" ADD CONSTRAINT "FK_743ea3d9e0e26d7cbb9c174e56b" FOREIGN KEY ("groupId") REFERENCES "group"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "note_group_permission" ADD CONSTRAINT "FK_fd5c9329d8b45cb160676f8d8c1" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "note_user_permission" ADD CONSTRAINT "FK_03cea81e07bab8864de026d517d" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "note_user_permission" ADD CONSTRAINT "FK_bc1ca3a87a9d662350d281a7f16" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "alias" ADD CONSTRAINT "FK_63012a303e6ca53144a8b7b64b0" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "note" ADD CONSTRAINT "FK_b09836eba01a8653c0628a78af8" FOREIGN KEY ("ownerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "revision" ADD CONSTRAINT "FK_8ac498c7c70de43d01b94fe7905" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "edit" ADD CONSTRAINT "FK_bbab22ed1a0e243b28623f4f48a" FOREIGN KEY ("authorId") REFERENCES "author"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "session" ADD CONSTRAINT "FK_e5da4837ed9d236532b3215a84e" FOREIGN KEY ("authorId") REFERENCES "author"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "author" ADD CONSTRAINT "FK_645811deaaaa772f9e6c2a4b927" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "identity" ADD CONSTRAINT "FK_12915039d2868ab654567bf5181" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "group_members_user" ADD CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f" FOREIGN KEY ("groupId") REFERENCES "group"("id") ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE "group_members_user" ADD CONSTRAINT "FK_427107c650638bcb2f1e167d2e5" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "revision_tags_tag" ADD CONSTRAINT "FK_3382f45eefeb40f91e45cfd4180" FOREIGN KEY ("revisionId") REFERENCES "revision"("id") ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE "revision_tags_tag" ADD CONSTRAINT "FK_19dbafe2a8b456c0ef40858d49f" FOREIGN KEY ("tagId") REFERENCES "tag"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "revision_edits_edit" ADD CONSTRAINT "FK_52c6a61e1a646768391c7854feb" FOREIGN KEY ("revisionId") REFERENCES "revision"("id") ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE "revision_edits_edit" ADD CONSTRAINT "FK_470886feb50e30114e39c426987" FOREIGN KEY ("editId") REFERENCES "edit"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "revision_edits_edit" DROP CONSTRAINT "FK_470886feb50e30114e39c426987"`, - ); - await queryRunner.query( - `ALTER TABLE "revision_edits_edit" DROP CONSTRAINT "FK_52c6a61e1a646768391c7854feb"`, - ); - await queryRunner.query( - `ALTER TABLE "revision_tags_tag" DROP CONSTRAINT "FK_19dbafe2a8b456c0ef40858d49f"`, - ); - await queryRunner.query( - `ALTER TABLE "revision_tags_tag" DROP CONSTRAINT "FK_3382f45eefeb40f91e45cfd4180"`, - ); - await queryRunner.query( - `ALTER TABLE "group_members_user" DROP CONSTRAINT "FK_427107c650638bcb2f1e167d2e5"`, - ); - await queryRunner.query( - `ALTER TABLE "group_members_user" DROP CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f"`, - ); - await queryRunner.query( - `ALTER TABLE "identity" DROP CONSTRAINT "FK_12915039d2868ab654567bf5181"`, - ); - await queryRunner.query( - `ALTER TABLE "author" DROP CONSTRAINT "FK_645811deaaaa772f9e6c2a4b927"`, - ); - await queryRunner.query( - `ALTER TABLE "session" DROP CONSTRAINT "FK_e5da4837ed9d236532b3215a84e"`, - ); - await queryRunner.query( - `ALTER TABLE "edit" DROP CONSTRAINT "FK_bbab22ed1a0e243b28623f4f48a"`, - ); - await queryRunner.query( - `ALTER TABLE "revision" DROP CONSTRAINT "FK_8ac498c7c70de43d01b94fe7905"`, - ); - await queryRunner.query( - `ALTER TABLE "note" DROP CONSTRAINT "FK_b09836eba01a8653c0628a78af8"`, - ); - await queryRunner.query( - `ALTER TABLE "alias" DROP CONSTRAINT "FK_63012a303e6ca53144a8b7b64b0"`, - ); - await queryRunner.query( - `ALTER TABLE "note_user_permission" DROP CONSTRAINT "FK_bc1ca3a87a9d662350d281a7f16"`, - ); - await queryRunner.query( - `ALTER TABLE "note_user_permission" DROP CONSTRAINT "FK_03cea81e07bab8864de026d517d"`, - ); - await queryRunner.query( - `ALTER TABLE "note_group_permission" DROP CONSTRAINT "FK_fd5c9329d8b45cb160676f8d8c1"`, - ); - await queryRunner.query( - `ALTER TABLE "note_group_permission" DROP CONSTRAINT "FK_743ea3d9e0e26d7cbb9c174e56b"`, - ); - await queryRunner.query( - `ALTER TABLE "media_upload" DROP CONSTRAINT "FK_73ce66b082df1df2003e305e9ac"`, - ); - await queryRunner.query( - `ALTER TABLE "media_upload" DROP CONSTRAINT "FK_edba6d4e0f3bcf6605772f0af6b"`, - ); - await queryRunner.query( - `ALTER TABLE "history_entry" DROP CONSTRAINT "FK_8f3595373fc9f6a32f126270422"`, - ); - await queryRunner.query( - `ALTER TABLE "history_entry" DROP CONSTRAINT "FK_42b8ae461cb58747a24340e6c64"`, - ); - await queryRunner.query( - `ALTER TABLE "api_token" DROP CONSTRAINT "FK_cbfc4e2b85b78207afb0b2d7fbc"`, - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_470886feb50e30114e39c42698"`, - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_52c6a61e1a646768391c7854fe"`, - ); - await queryRunner.query(`DROP TABLE "revision_edits_edit"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_19dbafe2a8b456c0ef40858d49"`, - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_3382f45eefeb40f91e45cfd418"`, - ); - await queryRunner.query(`DROP TABLE "revision_tags_tag"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_427107c650638bcb2f1e167d2e"`, - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_bfa303089d367a2e3c02b002b8"`, - ); - await queryRunner.query(`DROP TABLE "group_members_user"`); - await queryRunner.query(`DROP TABLE "identity"`); - await queryRunner.query(`DROP TABLE "user"`); - await queryRunner.query(`DROP TABLE "author"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_28c5d1d16da7908c97c9bc2f74"`, - ); - await queryRunner.query(`DROP TABLE "session"`); - await queryRunner.query(`DROP TABLE "edit"`); - await queryRunner.query(`DROP TABLE "revision"`); - await queryRunner.query(`DROP TABLE "tag"`); - await queryRunner.query(`DROP TABLE "note"`); - await queryRunner.query(`DROP TABLE "alias"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_5a3e91233d8878f98f5ad86b71"`, - ); - await queryRunner.query(`DROP TABLE "note_user_permission"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_ee1744842a9ef3ffbc05a7016a"`, - ); - await queryRunner.query(`DROP TABLE "note_group_permission"`); - await queryRunner.query(`DROP TABLE "group"`); - await queryRunner.query(`DROP TABLE "media_upload"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_928dd947355b0837366470a916"`, - ); - await queryRunner.query(`DROP TABLE "history_entry"`); - await queryRunner.query(`DROP TABLE "api_token"`); - } -} diff --git a/backend/src/migrations/sqlite-1726271503150-init.ts b/backend/src/migrations/sqlite-1726271503150-init.ts deleted file mode 100644 index caef476cf..000000000 --- a/backend/src/migrations/sqlite-1726271503150-init.ts +++ /dev/null @@ -1,496 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class Init1726271503150 implements MigrationInterface { - name = 'Init1726271503150'; - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "api_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "hash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_3e254e2eb542a65da7c405d0683" UNIQUE ("keyId"), CONSTRAINT "UQ_60221392192b32c7560c128a6fa" UNIQUE ("hash"))`, - ); - await queryRunner.query( - `CREATE TABLE "history_entry" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "pinStatus" boolean NOT NULL, "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer, "noteId" integer)`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_928dd947355b0837366470a916" ON "history_entry" ("noteId", "userId") `, - ); - await queryRunner.query( - `CREATE TABLE "media_upload" ("uuid" varchar PRIMARY KEY NOT NULL, "fileName" varchar NOT NULL, "backendType" varchar NOT NULL, "backendData" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer, "userId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "group" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "displayName" varchar NOT NULL, "special" boolean NOT NULL, CONSTRAINT "UQ_8a45300fd825918f3b40195fbdc" UNIQUE ("name"))`, - ); - await queryRunner.query( - `CREATE TABLE "note_group_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "groupId" integer, "noteId" integer)`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_ee1744842a9ef3ffbc05a7016a" ON "note_group_permission" ("groupId", "noteId") `, - ); - await queryRunner.query( - `CREATE TABLE "note_user_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "userId" integer, "noteId" integer)`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_5a3e91233d8878f98f5ad86b71" ON "note_user_permission" ("userId", "noteId") `, - ); - await queryRunner.query( - `CREATE TABLE "alias" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "primary" boolean, "noteId" integer, CONSTRAINT "UQ_89f27e45cc5c1e43abd9132c9b9" UNIQUE ("name"), CONSTRAINT "Only one primary alias per note" UNIQUE ("noteId", "primary"))`, - ); - await queryRunner.query( - `CREATE TABLE "note" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "publicId" text NOT NULL, "viewCount" integer NOT NULL DEFAULT (0), "version" integer NOT NULL DEFAULT (2), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "ownerId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "tag" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL)`, - ); - await queryRunner.query( - `CREATE TABLE "revision" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "patch" text NOT NULL, "title" text NOT NULL, "description" text NOT NULL, "content" text NOT NULL, "length" integer NOT NULL, "yjsStateVector" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "edit" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "startPos" integer NOT NULL, "endPos" integer NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "authorId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "session" ("id" varchar(255) PRIMARY KEY NOT NULL, "expiredAt" bigint NOT NULL, "json" text NOT NULL, "destroyedAt" datetime, "authorId" integer)`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_28c5d1d16da7908c97c9bc2f74" ON "session" ("expiredAt") `, - ); - await queryRunner.query( - `CREATE TABLE "author" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "color" integer NOT NULL, "userId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "user" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "username" varchar NOT NULL, "displayName" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "photo" text, "email" text, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"))`, - ); - await queryRunner.query( - `CREATE TABLE "identity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "providerType" varchar NOT NULL, "providerIdentifier" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "providerUserId" text, "passwordHash" text, "userId" integer)`, - ); - await queryRunner.query( - `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, PRIMARY KEY ("groupId", "userId"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, - ); - await queryRunner.query( - `CREATE TABLE "revision_tags_tag" ("revisionId" integer NOT NULL, "tagId" integer NOT NULL, PRIMARY KEY ("revisionId", "tagId"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_3382f45eefeb40f91e45cfd418" ON "revision_tags_tag" ("revisionId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_19dbafe2a8b456c0ef40858d49" ON "revision_tags_tag" ("tagId") `, - ); - await queryRunner.query( - `CREATE TABLE "revision_edits_edit" ("revisionId" integer NOT NULL, "editId" integer NOT NULL, PRIMARY KEY ("revisionId", "editId"))`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_52c6a61e1a646768391c7854fe" ON "revision_edits_edit" ("revisionId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, - ); - await queryRunner.query( - `CREATE TABLE "temporary_api_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "hash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_3e254e2eb542a65da7c405d0683" UNIQUE ("keyId"), CONSTRAINT "UQ_60221392192b32c7560c128a6fa" UNIQUE ("hash"), CONSTRAINT "FK_cbfc4e2b85b78207afb0b2d7fbc" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_api_token"("id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId") SELECT "id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId" FROM "api_token"`, - ); - await queryRunner.query(`DROP TABLE "api_token"`); - await queryRunner.query( - `ALTER TABLE "temporary_api_token" RENAME TO "api_token"`, - ); - await queryRunner.query(`DROP INDEX "IDX_928dd947355b0837366470a916"`); - await queryRunner.query( - `CREATE TABLE "temporary_history_entry" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "pinStatus" boolean NOT NULL, "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer, "noteId" integer, CONSTRAINT "FK_42b8ae461cb58747a24340e6c64" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_8f3595373fc9f6a32f126270422" FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_history_entry"("id", "pinStatus", "updatedAt", "userId", "noteId") SELECT "id", "pinStatus", "updatedAt", "userId", "noteId" FROM "history_entry"`, - ); - await queryRunner.query(`DROP TABLE "history_entry"`); - await queryRunner.query( - `ALTER TABLE "temporary_history_entry" RENAME TO "history_entry"`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_928dd947355b0837366470a916" ON "history_entry" ("noteId", "userId") `, - ); - await queryRunner.query( - `CREATE TABLE "temporary_media_upload" ("uuid" varchar PRIMARY KEY NOT NULL, "fileName" varchar NOT NULL, "backendType" varchar NOT NULL, "backendData" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer, "userId" integer, CONSTRAINT "FK_edba6d4e0f3bcf6605772f0af6b" FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_73ce66b082df1df2003e305e9ac" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_media_upload"("uuid", "fileName", "backendType", "backendData", "createdAt", "noteId", "userId") SELECT "uuid", "fileName", "backendType", "backendData", "createdAt", "noteId", "userId" FROM "media_upload"`, - ); - await queryRunner.query(`DROP TABLE "media_upload"`); - await queryRunner.query( - `ALTER TABLE "temporary_media_upload" RENAME TO "media_upload"`, - ); - await queryRunner.query(`DROP INDEX "IDX_ee1744842a9ef3ffbc05a7016a"`); - await queryRunner.query( - `CREATE TABLE "temporary_note_group_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "groupId" integer, "noteId" integer, CONSTRAINT "FK_743ea3d9e0e26d7cbb9c174e56b" FOREIGN KEY ("groupId") REFERENCES "group" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_fd5c9329d8b45cb160676f8d8c1" FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_note_group_permission"("id", "canEdit", "groupId", "noteId") SELECT "id", "canEdit", "groupId", "noteId" FROM "note_group_permission"`, - ); - await queryRunner.query(`DROP TABLE "note_group_permission"`); - await queryRunner.query( - `ALTER TABLE "temporary_note_group_permission" RENAME TO "note_group_permission"`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_ee1744842a9ef3ffbc05a7016a" ON "note_group_permission" ("groupId", "noteId") `, - ); - await queryRunner.query(`DROP INDEX "IDX_5a3e91233d8878f98f5ad86b71"`); - await queryRunner.query( - `CREATE TABLE "temporary_note_user_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "userId" integer, "noteId" integer, CONSTRAINT "FK_03cea81e07bab8864de026d517d" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_bc1ca3a87a9d662350d281a7f16" FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_note_user_permission"("id", "canEdit", "userId", "noteId") SELECT "id", "canEdit", "userId", "noteId" FROM "note_user_permission"`, - ); - await queryRunner.query(`DROP TABLE "note_user_permission"`); - await queryRunner.query( - `ALTER TABLE "temporary_note_user_permission" RENAME TO "note_user_permission"`, - ); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_5a3e91233d8878f98f5ad86b71" ON "note_user_permission" ("userId", "noteId") `, - ); - await queryRunner.query( - `CREATE TABLE "temporary_alias" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "primary" boolean, "noteId" integer, CONSTRAINT "UQ_89f27e45cc5c1e43abd9132c9b9" UNIQUE ("name"), CONSTRAINT "Only one primary alias per note" UNIQUE ("noteId", "primary"), CONSTRAINT "FK_63012a303e6ca53144a8b7b64b0" FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_alias"("id", "name", "primary", "noteId") SELECT "id", "name", "primary", "noteId" FROM "alias"`, - ); - await queryRunner.query(`DROP TABLE "alias"`); - await queryRunner.query(`ALTER TABLE "temporary_alias" RENAME TO "alias"`); - await queryRunner.query( - `CREATE TABLE "temporary_note" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "publicId" text NOT NULL, "viewCount" integer NOT NULL DEFAULT (0), "version" integer NOT NULL DEFAULT (2), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "ownerId" integer, CONSTRAINT "FK_b09836eba01a8653c0628a78af8" FOREIGN KEY ("ownerId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_note"("id", "publicId", "viewCount", "version", "createdAt", "ownerId") SELECT "id", "publicId", "viewCount", "version", "createdAt", "ownerId" FROM "note"`, - ); - await queryRunner.query(`DROP TABLE "note"`); - await queryRunner.query(`ALTER TABLE "temporary_note" RENAME TO "note"`); - await queryRunner.query( - `CREATE TABLE "temporary_revision" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "patch" text NOT NULL, "title" text NOT NULL, "description" text NOT NULL, "content" text NOT NULL, "length" integer NOT NULL, "yjsStateVector" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer, CONSTRAINT "FK_8ac498c7c70de43d01b94fe7905" FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_revision"("id", "patch", "title", "description", "content", "length", "yjsStateVector", "createdAt", "noteId") SELECT "id", "patch", "title", "description", "content", "length", "yjsStateVector", "createdAt", "noteId" FROM "revision"`, - ); - await queryRunner.query(`DROP TABLE "revision"`); - await queryRunner.query( - `ALTER TABLE "temporary_revision" RENAME TO "revision"`, - ); - await queryRunner.query( - `CREATE TABLE "temporary_edit" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "startPos" integer NOT NULL, "endPos" integer NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "authorId" integer, CONSTRAINT "FK_bbab22ed1a0e243b28623f4f48a" FOREIGN KEY ("authorId") REFERENCES "author" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_edit"("id", "startPos", "endPos", "createdAt", "updatedAt", "authorId") SELECT "id", "startPos", "endPos", "createdAt", "updatedAt", "authorId" FROM "edit"`, - ); - await queryRunner.query(`DROP TABLE "edit"`); - await queryRunner.query(`ALTER TABLE "temporary_edit" RENAME TO "edit"`); - await queryRunner.query(`DROP INDEX "IDX_28c5d1d16da7908c97c9bc2f74"`); - await queryRunner.query( - `CREATE TABLE "temporary_session" ("id" varchar(255) PRIMARY KEY NOT NULL, "expiredAt" bigint NOT NULL, "json" text NOT NULL, "destroyedAt" datetime, "authorId" integer, CONSTRAINT "FK_e5da4837ed9d236532b3215a84e" FOREIGN KEY ("authorId") REFERENCES "author" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_session"("id", "expiredAt", "json", "destroyedAt", "authorId") SELECT "id", "expiredAt", "json", "destroyedAt", "authorId" FROM "session"`, - ); - await queryRunner.query(`DROP TABLE "session"`); - await queryRunner.query( - `ALTER TABLE "temporary_session" RENAME TO "session"`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_28c5d1d16da7908c97c9bc2f74" ON "session" ("expiredAt") `, - ); - await queryRunner.query( - `CREATE TABLE "temporary_author" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "color" integer NOT NULL, "userId" integer, CONSTRAINT "FK_645811deaaaa772f9e6c2a4b927" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_author"("id", "color", "userId") SELECT "id", "color", "userId" FROM "author"`, - ); - await queryRunner.query(`DROP TABLE "author"`); - await queryRunner.query( - `ALTER TABLE "temporary_author" RENAME TO "author"`, - ); - await queryRunner.query( - `CREATE TABLE "temporary_identity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "providerType" varchar NOT NULL, "providerIdentifier" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "providerUserId" text, "passwordHash" text, "userId" integer, CONSTRAINT "FK_12915039d2868ab654567bf5181" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, - ); - await queryRunner.query( - `INSERT INTO "temporary_identity"("id", "providerType", "providerIdentifier", "createdAt", "updatedAt", "providerUserId", "passwordHash", "userId") SELECT "id", "providerType", "providerIdentifier", "createdAt", "updatedAt", "providerUserId", "passwordHash", "userId" FROM "identity"`, - ); - await queryRunner.query(`DROP TABLE "identity"`); - await queryRunner.query( - `ALTER TABLE "temporary_identity" RENAME TO "identity"`, - ); - await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); - await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); - await queryRunner.query( - `CREATE TABLE "temporary_group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f" FOREIGN KEY ("groupId") REFERENCES "group" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_427107c650638bcb2f1e167d2e5" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, PRIMARY KEY ("groupId", "userId"))`, - ); - await queryRunner.query( - `INSERT INTO "temporary_group_members_user"("groupId", "userId") SELECT "groupId", "userId" FROM "group_members_user"`, - ); - await queryRunner.query(`DROP TABLE "group_members_user"`); - await queryRunner.query( - `ALTER TABLE "temporary_group_members_user" RENAME TO "group_members_user"`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, - ); - await queryRunner.query(`DROP INDEX "IDX_3382f45eefeb40f91e45cfd418"`); - await queryRunner.query(`DROP INDEX "IDX_19dbafe2a8b456c0ef40858d49"`); - await queryRunner.query( - `CREATE TABLE "temporary_revision_tags_tag" ("revisionId" integer NOT NULL, "tagId" integer NOT NULL, CONSTRAINT "FK_3382f45eefeb40f91e45cfd4180" FOREIGN KEY ("revisionId") REFERENCES "revision" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_19dbafe2a8b456c0ef40858d49f" FOREIGN KEY ("tagId") REFERENCES "tag" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, PRIMARY KEY ("revisionId", "tagId"))`, - ); - await queryRunner.query( - `INSERT INTO "temporary_revision_tags_tag"("revisionId", "tagId") SELECT "revisionId", "tagId" FROM "revision_tags_tag"`, - ); - await queryRunner.query(`DROP TABLE "revision_tags_tag"`); - await queryRunner.query( - `ALTER TABLE "temporary_revision_tags_tag" RENAME TO "revision_tags_tag"`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_3382f45eefeb40f91e45cfd418" ON "revision_tags_tag" ("revisionId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_19dbafe2a8b456c0ef40858d49" ON "revision_tags_tag" ("tagId") `, - ); - await queryRunner.query(`DROP INDEX "IDX_52c6a61e1a646768391c7854fe"`); - await queryRunner.query(`DROP INDEX "IDX_470886feb50e30114e39c42698"`); - await queryRunner.query( - `CREATE TABLE "temporary_revision_edits_edit" ("revisionId" integer NOT NULL, "editId" integer NOT NULL, CONSTRAINT "FK_52c6a61e1a646768391c7854feb" FOREIGN KEY ("revisionId") REFERENCES "revision" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_470886feb50e30114e39c426987" FOREIGN KEY ("editId") REFERENCES "edit" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, PRIMARY KEY ("revisionId", "editId"))`, - ); - await queryRunner.query( - `INSERT INTO "temporary_revision_edits_edit"("revisionId", "editId") SELECT "revisionId", "editId" FROM "revision_edits_edit"`, - ); - await queryRunner.query(`DROP TABLE "revision_edits_edit"`); - await queryRunner.query( - `ALTER TABLE "temporary_revision_edits_edit" RENAME TO "revision_edits_edit"`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_52c6a61e1a646768391c7854fe" ON "revision_edits_edit" ("revisionId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX "IDX_470886feb50e30114e39c42698"`); - await queryRunner.query(`DROP INDEX "IDX_52c6a61e1a646768391c7854fe"`); - await queryRunner.query( - `ALTER TABLE "revision_edits_edit" RENAME TO "temporary_revision_edits_edit"`, - ); - await queryRunner.query( - `CREATE TABLE "revision_edits_edit" ("revisionId" integer NOT NULL, "editId" integer NOT NULL, PRIMARY KEY ("revisionId", "editId"))`, - ); - await queryRunner.query( - `INSERT INTO "revision_edits_edit"("revisionId", "editId") SELECT "revisionId", "editId" FROM "temporary_revision_edits_edit"`, - ); - await queryRunner.query(`DROP TABLE "temporary_revision_edits_edit"`); - await queryRunner.query( - `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_52c6a61e1a646768391c7854fe" ON "revision_edits_edit" ("revisionId") `, - ); - await queryRunner.query(`DROP INDEX "IDX_19dbafe2a8b456c0ef40858d49"`); - await queryRunner.query(`DROP INDEX "IDX_3382f45eefeb40f91e45cfd418"`); - await queryRunner.query( - `ALTER TABLE "revision_tags_tag" RENAME TO "temporary_revision_tags_tag"`, - ); - await queryRunner.query( - `CREATE TABLE "revision_tags_tag" ("revisionId" integer NOT NULL, "tagId" integer NOT NULL, PRIMARY KEY ("revisionId", "tagId"))`, - ); - await queryRunner.query( - `INSERT INTO "revision_tags_tag"("revisionId", "tagId") SELECT "revisionId", "tagId" FROM "temporary_revision_tags_tag"`, - ); - await queryRunner.query(`DROP TABLE "temporary_revision_tags_tag"`); - await queryRunner.query( - `CREATE INDEX "IDX_19dbafe2a8b456c0ef40858d49" ON "revision_tags_tag" ("tagId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_3382f45eefeb40f91e45cfd418" ON "revision_tags_tag" ("revisionId") `, - ); - await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); - await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); - await queryRunner.query( - `ALTER TABLE "group_members_user" RENAME TO "temporary_group_members_user"`, - ); - await queryRunner.query( - `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, PRIMARY KEY ("groupId", "userId"))`, - ); - await queryRunner.query( - `INSERT INTO "group_members_user"("groupId", "userId") SELECT "groupId", "userId" FROM "temporary_group_members_user"`, - ); - await queryRunner.query(`DROP TABLE "temporary_group_members_user"`); - await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, - ); - await queryRunner.query( - `ALTER TABLE "identity" RENAME TO "temporary_identity"`, - ); - await queryRunner.query( - `CREATE TABLE "identity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "providerType" varchar NOT NULL, "providerIdentifier" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "providerUserId" text, "passwordHash" text, "userId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "identity"("id", "providerType", "providerIdentifier", "createdAt", "updatedAt", "providerUserId", "passwordHash", "userId") SELECT "id", "providerType", "providerIdentifier", "createdAt", "updatedAt", "providerUserId", "passwordHash", "userId" FROM "temporary_identity"`, - ); - await queryRunner.query(`DROP TABLE "temporary_identity"`); - await queryRunner.query( - `ALTER TABLE "author" RENAME TO "temporary_author"`, - ); - await queryRunner.query( - `CREATE TABLE "author" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "color" integer NOT NULL, "userId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "author"("id", "color", "userId") SELECT "id", "color", "userId" FROM "temporary_author"`, - ); - await queryRunner.query(`DROP TABLE "temporary_author"`); - await queryRunner.query(`DROP INDEX "IDX_28c5d1d16da7908c97c9bc2f74"`); - await queryRunner.query( - `ALTER TABLE "session" RENAME TO "temporary_session"`, - ); - await queryRunner.query( - `CREATE TABLE "session" ("id" varchar(255) PRIMARY KEY NOT NULL, "expiredAt" bigint NOT NULL, "json" text NOT NULL, "destroyedAt" datetime, "authorId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "session"("id", "expiredAt", "json", "destroyedAt", "authorId") SELECT "id", "expiredAt", "json", "destroyedAt", "authorId" FROM "temporary_session"`, - ); - await queryRunner.query(`DROP TABLE "temporary_session"`); - await queryRunner.query( - `CREATE INDEX "IDX_28c5d1d16da7908c97c9bc2f74" ON "session" ("expiredAt") `, - ); - await queryRunner.query(`ALTER TABLE "edit" RENAME TO "temporary_edit"`); - await queryRunner.query( - `CREATE TABLE "edit" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "startPos" integer NOT NULL, "endPos" integer NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "authorId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "edit"("id", "startPos", "endPos", "createdAt", "updatedAt", "authorId") SELECT "id", "startPos", "endPos", "createdAt", "updatedAt", "authorId" FROM "temporary_edit"`, - ); - await queryRunner.query(`DROP TABLE "temporary_edit"`); - await queryRunner.query( - `ALTER TABLE "revision" RENAME TO "temporary_revision"`, - ); - await queryRunner.query( - `CREATE TABLE "revision" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "patch" text NOT NULL, "title" text NOT NULL, "description" text NOT NULL, "content" text NOT NULL, "length" integer NOT NULL, "yjsStateVector" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "revision"("id", "patch", "title", "description", "content", "length", "yjsStateVector", "createdAt", "noteId") SELECT "id", "patch", "title", "description", "content", "length", "yjsStateVector", "createdAt", "noteId" FROM "temporary_revision"`, - ); - await queryRunner.query(`DROP TABLE "temporary_revision"`); - await queryRunner.query(`ALTER TABLE "note" RENAME TO "temporary_note"`); - await queryRunner.query( - `CREATE TABLE "note" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "publicId" text NOT NULL, "viewCount" integer NOT NULL DEFAULT (0), "version" integer NOT NULL DEFAULT (2), "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "ownerId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "note"("id", "publicId", "viewCount", "version", "createdAt", "ownerId") SELECT "id", "publicId", "viewCount", "version", "createdAt", "ownerId" FROM "temporary_note"`, - ); - await queryRunner.query(`DROP TABLE "temporary_note"`); - await queryRunner.query(`ALTER TABLE "alias" RENAME TO "temporary_alias"`); - await queryRunner.query( - `CREATE TABLE "alias" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "primary" boolean, "noteId" integer, CONSTRAINT "UQ_89f27e45cc5c1e43abd9132c9b9" UNIQUE ("name"), CONSTRAINT "Only one primary alias per note" UNIQUE ("noteId", "primary"))`, - ); - await queryRunner.query( - `INSERT INTO "alias"("id", "name", "primary", "noteId") SELECT "id", "name", "primary", "noteId" FROM "temporary_alias"`, - ); - await queryRunner.query(`DROP TABLE "temporary_alias"`); - await queryRunner.query(`DROP INDEX "IDX_5a3e91233d8878f98f5ad86b71"`); - await queryRunner.query( - `ALTER TABLE "note_user_permission" RENAME TO "temporary_note_user_permission"`, - ); - await queryRunner.query( - `CREATE TABLE "note_user_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "userId" integer, "noteId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "note_user_permission"("id", "canEdit", "userId", "noteId") SELECT "id", "canEdit", "userId", "noteId" FROM "temporary_note_user_permission"`, - ); - await queryRunner.query(`DROP TABLE "temporary_note_user_permission"`); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_5a3e91233d8878f98f5ad86b71" ON "note_user_permission" ("userId", "noteId") `, - ); - await queryRunner.query(`DROP INDEX "IDX_ee1744842a9ef3ffbc05a7016a"`); - await queryRunner.query( - `ALTER TABLE "note_group_permission" RENAME TO "temporary_note_group_permission"`, - ); - await queryRunner.query( - `CREATE TABLE "note_group_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "groupId" integer, "noteId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "note_group_permission"("id", "canEdit", "groupId", "noteId") SELECT "id", "canEdit", "groupId", "noteId" FROM "temporary_note_group_permission"`, - ); - await queryRunner.query(`DROP TABLE "temporary_note_group_permission"`); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_ee1744842a9ef3ffbc05a7016a" ON "note_group_permission" ("groupId", "noteId") `, - ); - await queryRunner.query( - `ALTER TABLE "media_upload" RENAME TO "temporary_media_upload"`, - ); - await queryRunner.query( - `CREATE TABLE "media_upload" ("uuid" varchar PRIMARY KEY NOT NULL, "fileName" varchar NOT NULL, "backendType" varchar NOT NULL, "backendData" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer, "userId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "media_upload"("uuid", "fileName", "backendType", "backendData", "createdAt", "noteId", "userId") SELECT "uuid", "fileName", "backendType", "backendData", "createdAt", "noteId", "userId" FROM "temporary_media_upload"`, - ); - await queryRunner.query(`DROP TABLE "temporary_media_upload"`); - await queryRunner.query(`DROP INDEX "IDX_928dd947355b0837366470a916"`); - await queryRunner.query( - `ALTER TABLE "history_entry" RENAME TO "temporary_history_entry"`, - ); - await queryRunner.query( - `CREATE TABLE "history_entry" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "pinStatus" boolean NOT NULL, "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer, "noteId" integer)`, - ); - await queryRunner.query( - `INSERT INTO "history_entry"("id", "pinStatus", "updatedAt", "userId", "noteId") SELECT "id", "pinStatus", "updatedAt", "userId", "noteId" FROM "temporary_history_entry"`, - ); - await queryRunner.query(`DROP TABLE "temporary_history_entry"`); - await queryRunner.query( - `CREATE UNIQUE INDEX "IDX_928dd947355b0837366470a916" ON "history_entry" ("noteId", "userId") `, - ); - await queryRunner.query( - `ALTER TABLE "api_token" RENAME TO "temporary_api_token"`, - ); - await queryRunner.query( - `CREATE TABLE "api_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "hash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_3e254e2eb542a65da7c405d0683" UNIQUE ("keyId"), CONSTRAINT "UQ_60221392192b32c7560c128a6fa" UNIQUE ("hash"))`, - ); - await queryRunner.query( - `INSERT INTO "api_token"("id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId") SELECT "id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId" FROM "temporary_api_token"`, - ); - await queryRunner.query(`DROP TABLE "temporary_api_token"`); - await queryRunner.query(`DROP INDEX "IDX_470886feb50e30114e39c42698"`); - await queryRunner.query(`DROP INDEX "IDX_52c6a61e1a646768391c7854fe"`); - await queryRunner.query(`DROP TABLE "revision_edits_edit"`); - await queryRunner.query(`DROP INDEX "IDX_19dbafe2a8b456c0ef40858d49"`); - await queryRunner.query(`DROP INDEX "IDX_3382f45eefeb40f91e45cfd418"`); - await queryRunner.query(`DROP TABLE "revision_tags_tag"`); - await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); - await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); - await queryRunner.query(`DROP TABLE "group_members_user"`); - await queryRunner.query(`DROP TABLE "identity"`); - await queryRunner.query(`DROP TABLE "user"`); - await queryRunner.query(`DROP TABLE "author"`); - await queryRunner.query(`DROP INDEX "IDX_28c5d1d16da7908c97c9bc2f74"`); - await queryRunner.query(`DROP TABLE "session"`); - await queryRunner.query(`DROP TABLE "edit"`); - await queryRunner.query(`DROP TABLE "revision"`); - await queryRunner.query(`DROP TABLE "tag"`); - await queryRunner.query(`DROP TABLE "note"`); - await queryRunner.query(`DROP TABLE "alias"`); - await queryRunner.query(`DROP INDEX "IDX_5a3e91233d8878f98f5ad86b71"`); - await queryRunner.query(`DROP TABLE "note_user_permission"`); - await queryRunner.query(`DROP INDEX "IDX_ee1744842a9ef3ffbc05a7016a"`); - await queryRunner.query(`DROP TABLE "note_group_permission"`); - await queryRunner.query(`DROP TABLE "group"`); - await queryRunner.query(`DROP TABLE "media_upload"`); - await queryRunner.query(`DROP INDEX "IDX_928dd947355b0837366470a916"`); - await queryRunner.query(`DROP TABLE "history_entry"`); - await queryRunner.query(`DROP TABLE "api_token"`); - } -} diff --git a/backend/src/notes/alias.entity.ts b/backend/src/notes/alias.entity.ts deleted file mode 100644 index 0bbacafd5..000000000 --- a/backend/src/notes/alias.entity.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - Entity, - ManyToOne, - PrimaryGeneratedColumn, - Unique, -} from 'typeorm'; - -import { Note } from './note.entity'; -import { PrimaryValueTransformer } from './primary.value-transformer'; - -@Entity() -@Unique('Only one primary alias per note', ['note', 'primary']) -export class Alias { - @PrimaryGeneratedColumn() - id: number; - - /** - * the actual alias - */ - @Column({ - nullable: false, - unique: true, - }) - name: string; - - /** - * Is this alias the primary alias, by which people access the note? - */ - @Column({ - /* - Because of the @Unique at the top of this entity, this field must be saved as null instead of false in the DB. - If a non-primary alias would be saved with `primary: false` it would only be possible to have one non-primary and one primary alias. - But a nullable field does not have such problems. - This way the DB keeps track that one note really only has one primary alias. - */ - comment: - 'This field tells you if this is the primary alias of the note. If this field is null, that means this alias is not primary.', - nullable: true, - transformer: new PrimaryValueTransformer(), - }) - primary: boolean; - - @ManyToOne((_) => Note, (note) => note.aliases, { - onDelete: 'CASCADE', // This deletes the Alias, when the associated Note is deleted - }) - note: Promise; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - static create(name: string, note: Note, primary: boolean): Omit { - const alias = new Alias(); - alias.name = name; - alias.primary = primary; - alias.note = Promise.resolve(note); - return alias; - } -} diff --git a/backend/src/notes/alias.service.spec.ts b/backend/src/notes/alias.service.spec.ts index ed3d7acaa..e93685f84 100644 --- a/backend/src/notes/alias.service.spec.ts +++ b/backend/src/notes/alias.service.spec.ts @@ -17,6 +17,7 @@ import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; import databaseConfigMock from '../config/mock/database.config.mock'; import noteConfigMock from '../config/mock/note.config.mock'; +import { User } from '../database/user.entity'; import { AlreadyInDBError, ForbiddenIdError, @@ -34,7 +35,6 @@ import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; import { RevisionsModule } from '../revisions/revisions.module'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { mockSelectQueryBuilderInRepo } from '../utils/test-utils/mockSelectQueryBuilder'; import { Alias } from './alias.entity'; diff --git a/backend/src/notes/note.entity.ts b/backend/src/notes/note.entity.ts deleted file mode 100644 index 5f69bb3a4..000000000 --- a/backend/src/notes/note.entity.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - CreateDateColumn, - Entity, - ManyToOne, - OneToMany, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { HistoryEntry } from '../history/history-entry.entity'; -import { MediaUpload } from '../media/media-upload.entity'; -import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; -import { NoteUserPermission } from '../permissions/note-user-permission.entity'; -import { Revision } from '../revisions/revision.entity'; -import { User } from '../users/user.entity'; -import { Alias } from './alias.entity'; -import { generatePublicId } from './utils'; - -@Entity() -export class Note { - @PrimaryGeneratedColumn() - id: number; - - @Column({ type: 'text' }) - publicId: string; - - @OneToMany( - (_) => Alias, - (alias) => alias.note, - { cascade: true }, // This ensures that embedded Aliases are automatically saved to the database - ) - aliases: Promise; - - @OneToMany( - (_) => NoteGroupPermission, - (groupPermission) => groupPermission.note, - { cascade: true }, // This ensures that embedded NoteGroupPermissions are automatically saved to the database - ) - groupPermissions: Promise; - - @OneToMany( - (_) => NoteUserPermission, - (userPermission) => userPermission.note, - { cascade: true }, // This ensures that embedded NoteUserPermission are automatically saved to the database - ) - userPermissions: Promise; - - @Column({ - nullable: false, - default: 0, - }) - viewCount: number; - - @ManyToOne((_) => User, (user) => user.ownedNotes, { - onDelete: 'CASCADE', // This deletes the Note, when the associated User is deleted - nullable: true, - }) - owner: Promise; - - @OneToMany((_) => Revision, (revision) => revision.note, { cascade: true }) - revisions: Promise; - - @OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user) - historyEntries: Promise; - - @OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note) - mediaUploads: Promise; - - @Column({ - default: 2, - }) - version: number; - - @CreateDateColumn() - createdAt: Date; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - /** - * Creates a new Note - * @param owner The owner of the note - * @param alias Optional primary alias - */ - public static create( - owner: User | null, - alias?: string, - ): Omit { - const newNote = new Note(); - newNote.publicId = generatePublicId(); - newNote.aliases = alias - ? Promise.resolve([Alias.create(alias, newNote, true) as Alias]) - : Promise.resolve([]); - newNote.userPermissions = Promise.resolve([]); - newNote.groupPermissions = Promise.resolve([]); - newNote.viewCount = 0; - newNote.owner = Promise.resolve(owner); - newNote.revisions = Promise.resolve([]); - newNote.historyEntries = Promise.resolve([]); - newNote.mediaUploads = Promise.resolve([]); - newNote.version = 2; - return newNote; - } -} diff --git a/backend/src/notes/notes.module.ts b/backend/src/notes/notes.module.ts index f07774078..68fadeff3 100644 --- a/backend/src/notes/notes.module.ts +++ b/backend/src/notes/notes.module.ts @@ -7,13 +7,13 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { User } from '../database/user.entity'; import { GroupsModule } from '../groups/groups.module'; import { LoggerModule } from '../logger/logger.module'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; import { RealtimeNoteModule } from '../realtime/realtime-note/realtime-note.module'; import { RevisionsModule } from '../revisions/revisions.module'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { Alias } from './alias.entity'; import { AliasService } from './alias.service'; diff --git a/backend/src/notes/notes.service.spec.ts b/backend/src/notes/notes.service.spec.ts index f71ad0337..6b715f16e 100644 --- a/backend/src/notes/notes.service.spec.ts +++ b/backend/src/notes/notes.service.spec.ts @@ -27,6 +27,7 @@ import { registerNoteConfig, } from '../config/mock/note.config.mock'; import { NoteConfig } from '../config/note.config'; +import { User } from '../database/user.entity'; import { AlreadyInDBError, ForbiddenIdError, @@ -46,7 +47,6 @@ import { Revision } from '../revisions/revision.entity'; import { RevisionsModule } from '../revisions/revisions.module'; import { RevisionsService } from '../revisions/revisions.service'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { mockSelectQueryBuilderInRepo } from '../utils/test-utils/mockSelectQueryBuilder'; import { Alias } from './alias.entity'; diff --git a/backend/src/notes/notes.service.ts b/backend/src/notes/notes.service.ts index fdd366d7c..af9e9d1be 100644 --- a/backend/src/notes/notes.service.ts +++ b/backend/src/notes/notes.service.ts @@ -16,6 +16,7 @@ import { Repository } from 'typeorm'; import { DefaultAccessLevel } from '../config/default-access-level.enum'; import noteConfiguration, { NoteConfig } from '../config/note.config'; +import { User } from '../database/user.entity'; import { AlreadyInDBError, ForbiddenIdError, @@ -31,7 +32,6 @@ import { NoteGroupPermission } from '../permissions/note-group-permission.entity import { RealtimeNoteStore } from '../realtime/realtime-note/realtime-note-store'; import { RealtimeNoteService } from '../realtime/realtime-note/realtime-note.service'; import { RevisionsService } from '../revisions/revisions.service'; -import { User } from '../users/user.entity'; import { UsersService } from '../users/users.service'; import { Alias } from './alias.entity'; import { AliasService } from './alias.service'; diff --git a/backend/src/notes/tag.entity.ts b/backend/src/notes/tag.entity.ts deleted file mode 100644 index 8907100d1..000000000 --- a/backend/src/notes/tag.entity.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm'; - -import { Revision } from '../revisions/revision.entity'; - -@Entity() -export class Tag { - @PrimaryGeneratedColumn() - id: number; - - @Column({ - nullable: false, - }) - name: string; - - @ManyToMany((_) => Revision, (revision) => revision.tags) - revisions: Promise; -} diff --git a/backend/src/notes/utils.spec.ts b/backend/src/notes/utils.spec.ts index 38c9ff35b..4ee601477 100644 --- a/backend/src/notes/utils.spec.ts +++ b/backend/src/notes/utils.spec.ts @@ -5,7 +5,7 @@ */ import { randomBytes } from 'crypto'; -import { User } from '../users/user.entity'; +import { User } from '../database/user.entity'; import { Alias } from './alias.entity'; import { Note } from './note.entity'; import { generatePublicId, getPrimaryAlias } from './utils'; diff --git a/backend/src/permissions/note-group-permission.entity.ts b/backend/src/permissions/note-group-permission.entity.ts deleted file mode 100644 index b0947789c..000000000 --- a/backend/src/permissions/note-group-permission.entity.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - Entity, - Index, - ManyToOne, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { Group } from '../groups/group.entity'; -import { Note } from '../notes/note.entity'; - -@Entity() -@Index(['group', 'note'], { unique: true }) -export class NoteGroupPermission { - @PrimaryGeneratedColumn() - id: number; - - @ManyToOne((_) => Group, { - onDelete: 'CASCADE', // This deletes the NoteGroupPermission, when the associated Group is deleted - orphanedRowAction: 'delete', // This ensures the row of the NoteGroupPermission is deleted when no group references it anymore - }) - group: Promise; - - @ManyToOne((_) => Note, (note) => note.groupPermissions, { - onDelete: 'CASCADE', // This deletes the NoteGroupPermission, when the associated Note is deleted - orphanedRowAction: 'delete', // This ensures the row of the NoteGroupPermission is deleted when no note references it anymore - }) - note: Promise; - - @Column() - canEdit: boolean; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - public static create( - group: Group, - note: Note, - canEdit: boolean, - ): NoteGroupPermission { - const groupPermission = new NoteGroupPermission(); - groupPermission.group = Promise.resolve(group); - groupPermission.note = Promise.resolve(note); - groupPermission.canEdit = canEdit; - return groupPermission; - } -} diff --git a/backend/src/permissions/note-user-permission.entity.ts b/backend/src/permissions/note-user-permission.entity.ts deleted file mode 100644 index 30a65515e..000000000 --- a/backend/src/permissions/note-user-permission.entity.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - Entity, - Index, - ManyToOne, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; - -@Entity() -@Index(['user', 'note'], { unique: true }) -export class NoteUserPermission { - @PrimaryGeneratedColumn() - id: number; - - @ManyToOne((_) => User, { - onDelete: 'CASCADE', // This deletes the NoteUserPermission, when the associated Note is deleted - orphanedRowAction: 'delete', // This ensures the row of the NoteUserPermission is deleted when no user references it anymore - }) - user: Promise; - - @ManyToOne((_) => Note, (note) => note.userPermissions, { - onDelete: 'CASCADE', // This deletes the NoteUserPermission, when the associated Note is deleted - orphanedRowAction: 'delete', // This ensures the row of the NoteUserPermission is deleted when no note references it anymore - }) - note: Promise; - - @Column() - canEdit: boolean; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - public static create( - user: User, - note: Note, - canEdit: boolean, - ): NoteUserPermission { - const userPermission = new NoteUserPermission(); - userPermission.user = Promise.resolve(user); - userPermission.note = Promise.resolve(note); - userPermission.canEdit = canEdit; - return userPermission; - } -} diff --git a/backend/src/permissions/permissions.guard.spec.ts b/backend/src/permissions/permissions.guard.spec.ts index a5bd3d3f7..a6ffacee0 100644 --- a/backend/src/permissions/permissions.guard.spec.ts +++ b/backend/src/permissions/permissions.guard.spec.ts @@ -9,9 +9,9 @@ import { Mock } from 'ts-mockery'; import * as ExtractNoteIdOrAliasModule from '../api/utils/extract-note-from-request'; import { CompleteRequest } from '../api/utils/request.type'; +import { User } from '../database/user.entity'; import { ConsoleLoggerService } from '../logger/console-logger.service'; import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; import { getNotePermissionDisplayName, NotePermission, diff --git a/backend/src/permissions/permissions.service.spec.ts b/backend/src/permissions/permissions.service.spec.ts index c07138bc9..5313562d5 100644 --- a/backend/src/permissions/permissions.service.spec.ts +++ b/backend/src/permissions/permissions.service.spec.ts @@ -27,6 +27,7 @@ import { registerNoteConfig, } from '../config/mock/note.config.mock'; import { NoteConfig } from '../config/note.config'; +import { User } from '../database/user.entity'; import { PermissionsUpdateInconsistentError } from '../errors/errors'; import { eventModuleConfig, NoteEvent } from '../events'; import { Group } from '../groups/group.entity'; @@ -41,7 +42,6 @@ import { Tag } from '../notes/tag.entity'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { NoteGroupPermission } from './note-group-permission.entity'; import { diff --git a/backend/src/permissions/permissions.service.ts b/backend/src/permissions/permissions.service.ts index 386872a32..88e972f0c 100644 --- a/backend/src/permissions/permissions.service.ts +++ b/backend/src/permissions/permissions.service.ts @@ -10,6 +10,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import noteConfiguration, { NoteConfig } from '../config/note.config'; +import { User } from '../database/user.entity'; import { PermissionsUpdateInconsistentError } from '../errors/errors'; import { NoteEvent, NoteEventMap } from '../events'; import { Group } from '../groups/group.entity'; @@ -17,7 +18,6 @@ import { GroupsService } from '../groups/groups.service'; import { ConsoleLoggerService } from '../logger/console-logger.service'; import { MediaUpload } from '../media/media-upload.entity'; import { Note } from '../notes/note.entity'; -import { User } from '../users/user.entity'; import { UsersService } from '../users/users.service'; import { checkArrayForDuplicates } from '../utils/arrayDuplicatCheck'; import { NoteGroupPermission } from './note-group-permission.entity'; diff --git a/backend/src/permissions/utils/find-highest-note-permission-by-group.spec.ts b/backend/src/permissions/utils/find-highest-note-permission-by-group.spec.ts index 6d5533d62..df17a5299 100644 --- a/backend/src/permissions/utils/find-highest-note-permission-by-group.spec.ts +++ b/backend/src/permissions/utils/find-highest-note-permission-by-group.spec.ts @@ -5,9 +5,9 @@ */ import { Mock } from 'ts-mockery'; +import { User } from '../../database/user.entity'; import { Group } from '../../groups/group.entity'; import { SpecialGroup } from '../../groups/groups.special'; -import { User } from '../../users/user.entity'; import { NoteGroupPermission } from '../note-group-permission.entity'; import { NotePermission } from '../note-permission.enum'; import { findHighestNotePermissionByGroup } from './find-highest-note-permission-by-group'; diff --git a/backend/src/permissions/utils/find-highest-note-permission-by-group.ts b/backend/src/permissions/utils/find-highest-note-permission-by-group.ts index 1b57279f4..8e31a89b4 100644 --- a/backend/src/permissions/utils/find-highest-note-permission-by-group.ts +++ b/backend/src/permissions/utils/find-highest-note-permission-by-group.ts @@ -3,9 +3,9 @@ * * SPDX-License-Identifier: AGPL-3.0-only */ +import { User } from '../../database/user.entity'; import { Group } from '../../groups/group.entity'; import { SpecialGroup } from '../../groups/groups.special'; -import { User } from '../../users/user.entity'; import { NoteGroupPermission } from '../note-group-permission.entity'; import { NotePermission } from '../note-permission.enum'; diff --git a/backend/src/permissions/utils/find-highest-note-permission-by-user.spec.ts b/backend/src/permissions/utils/find-highest-note-permission-by-user.spec.ts index c59f5b7c7..778b24009 100644 --- a/backend/src/permissions/utils/find-highest-note-permission-by-user.spec.ts +++ b/backend/src/permissions/utils/find-highest-note-permission-by-user.spec.ts @@ -5,7 +5,7 @@ */ import { Mock } from 'ts-mockery'; -import { User } from '../../users/user.entity'; +import { User } from '../../database/user.entity'; import { NotePermission } from '../note-permission.enum'; import { NoteUserPermission } from '../note-user-permission.entity'; import { findHighestNotePermissionByUser } from './find-highest-note-permission-by-user'; diff --git a/backend/src/permissions/utils/find-highest-note-permission-by-user.ts b/backend/src/permissions/utils/find-highest-note-permission-by-user.ts index 67bb9a799..840192e5b 100644 --- a/backend/src/permissions/utils/find-highest-note-permission-by-user.ts +++ b/backend/src/permissions/utils/find-highest-note-permission-by-user.ts @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: AGPL-3.0-only */ -import { User } from '../../users/user.entity'; +import { User } from '../../database/user.entity'; import { NotePermission } from '../note-permission.enum'; import { NoteUserPermission } from '../note-user-permission.entity'; diff --git a/backend/src/realtime/realtime-note/realtime-connection.spec.ts b/backend/src/realtime/realtime-note/realtime-connection.spec.ts index 486d548c2..348b59a16 100644 --- a/backend/src/realtime/realtime-note/realtime-connection.spec.ts +++ b/backend/src/realtime/realtime-note/realtime-connection.spec.ts @@ -11,8 +11,8 @@ import { import * as HedgeDocCommonsModule from '@hedgedoc/commons'; import { Mock } from 'ts-mockery'; +import { User } from '../../database/user.entity'; import { Note } from '../../notes/note.entity'; -import { User } from '../../users/user.entity'; import * as NameRandomizerModule from './random-word-lists/name-randomizer'; import { RealtimeConnection } from './realtime-connection'; import { RealtimeNote } from './realtime-note'; diff --git a/backend/src/realtime/realtime-note/realtime-connection.ts b/backend/src/realtime/realtime-note/realtime-connection.ts index 414f786c4..a8d71d8cb 100644 --- a/backend/src/realtime/realtime-note/realtime-connection.ts +++ b/backend/src/realtime/realtime-note/realtime-connection.ts @@ -6,7 +6,7 @@ import { MessageTransporter, YDocSyncServerAdapter } from '@hedgedoc/commons'; import { Logger } from '@nestjs/common'; -import { User } from '../../users/user.entity'; +import { User } from '../../database/user.entity'; import { generateRandomName } from './random-word-lists/name-randomizer'; import { RealtimeNote } from './realtime-note'; import { RealtimeUserStatusAdapter } from './realtime-user-status-adapter'; diff --git a/backend/src/realtime/realtime-note/realtime-note.service.spec.ts b/backend/src/realtime/realtime-note/realtime-note.service.spec.ts index 8232b4e11..958d3771a 100644 --- a/backend/src/realtime/realtime-note/realtime-note.service.spec.ts +++ b/backend/src/realtime/realtime-note/realtime-note.service.spec.ts @@ -7,13 +7,13 @@ import { SchedulerRegistry } from '@nestjs/schedule'; import { Mock } from 'ts-mockery'; import { AppConfig } from '../../config/app.config'; +import { User } from '../../database/user.entity'; import { ConsoleLoggerService } from '../../logger/console-logger.service'; import { Note } from '../../notes/note.entity'; import { NotePermission } from '../../permissions/note-permission.enum'; import { PermissionsService } from '../../permissions/permissions.service'; import { Revision } from '../../revisions/revision.entity'; import { RevisionsService } from '../../revisions/revisions.service'; -import { User } from '../../users/user.entity'; import { RealtimeConnection } from './realtime-connection'; import { RealtimeNote } from './realtime-note'; import { RealtimeNoteStore } from './realtime-note-store'; diff --git a/backend/src/realtime/realtime-note/test-utils/mock-connection.ts b/backend/src/realtime/realtime-note/test-utils/mock-connection.ts index f32badb14..f25cc427e 100644 --- a/backend/src/realtime/realtime-note/test-utils/mock-connection.ts +++ b/backend/src/realtime/realtime-note/test-utils/mock-connection.ts @@ -9,7 +9,7 @@ import { } from '@hedgedoc/commons'; import { Mock } from 'ts-mockery'; -import { User } from '../../../users/user.entity'; +import { User } from '../../../database/user.entity'; import { RealtimeConnection } from '../realtime-connection'; import { RealtimeNote } from '../realtime-note'; import { RealtimeUserStatusAdapter } from '../realtime-user-status-adapter'; diff --git a/backend/src/realtime/websocket/websocket.gateway.spec.ts b/backend/src/realtime/websocket/websocket.gateway.spec.ts index fbfed1266..38167412a 100644 --- a/backend/src/realtime/websocket/websocket.gateway.spec.ts +++ b/backend/src/realtime/websocket/websocket.gateway.spec.ts @@ -20,6 +20,7 @@ import appConfigMock from '../../config/mock/app.config.mock'; import authConfigMock from '../../config/mock/auth.config.mock'; import databaseConfigMock from '../../config/mock/database.config.mock'; import noteConfigMock from '../../config/mock/note.config.mock'; +import { User } from '../../database/user.entity'; import { eventModuleConfig } from '../../events'; import { Group } from '../../groups/group.entity'; import { LoggerModule } from '../../logger/logger.module'; @@ -38,7 +39,6 @@ import { Revision } from '../../revisions/revision.entity'; import { Session } from '../../sessions/session.entity'; import { SessionModule } from '../../sessions/session.module'; import { SessionService } from '../../sessions/session.service'; -import { User } from '../../users/user.entity'; import { UsersModule } from '../../users/users.module'; import { UsersService } from '../../users/users.service'; import * as websocketConnectionModule from '../realtime-note/realtime-connection'; diff --git a/backend/src/realtime/websocket/websocket.gateway.ts b/backend/src/realtime/websocket/websocket.gateway.ts index 5968f9c9b..f51607295 100644 --- a/backend/src/realtime/websocket/websocket.gateway.ts +++ b/backend/src/realtime/websocket/websocket.gateway.ts @@ -12,12 +12,12 @@ import { OnGatewayConnection, WebSocketGateway } from '@nestjs/websockets'; import { IncomingMessage } from 'http'; import WebSocket from 'ws'; +import { User } from '../../database/user.entity'; import { ConsoleLoggerService } from '../../logger/console-logger.service'; import { NotesService } from '../../notes/notes.service'; import { NotePermission } from '../../permissions/note-permission.enum'; import { PermissionsService } from '../../permissions/permissions.service'; import { SessionService } from '../../sessions/session.service'; -import { User } from '../../users/user.entity'; import { UsersService } from '../../users/users.service'; import { RealtimeConnection } from '../realtime-note/realtime-connection'; import { RealtimeNoteService } from '../realtime-note/realtime-note.service'; diff --git a/backend/src/revisions/edit.entity.ts b/backend/src/revisions/edit.entity.ts deleted file mode 100644 index bcb64d014..000000000 --- a/backend/src/revisions/edit.entity.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - CreateDateColumn, - Entity, - ManyToMany, - ManyToOne, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { Author } from '../authors/author.entity'; -import { Revision } from './revision.entity'; - -/** - * The Edit represents a change in the content of a note by a particular {@link Author} - */ -@Entity() -export class Edit { - @PrimaryGeneratedColumn() - id: number; - - /** - * Revisions this edit appears in - */ - @ManyToMany((_) => Revision, (revision) => revision.edits) - revisions: Promise; - - /** - * Author that created the change - */ - @ManyToOne(() => Author, (author) => author.edits) - author: Promise; - - @Column() - startPos: number; - - @Column() - endPos: number; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - public static create( - author: Author, - startPos: number, - endPos: number, - ): Omit { - const newEdit = new Edit(); - newEdit.revisions = Promise.resolve([]); - newEdit.author = Promise.resolve(author); - newEdit.startPos = startPos; - newEdit.endPos = endPos; - return newEdit; - } -} diff --git a/backend/src/revisions/revision.entity.ts b/backend/src/revisions/revision.entity.ts deleted file mode 100644 index cdd770220..000000000 --- a/backend/src/revisions/revision.entity.ts +++ /dev/null @@ -1,115 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - CreateDateColumn, - Entity, - JoinTable, - ManyToMany, - ManyToOne, - PrimaryGeneratedColumn, -} from 'typeorm'; - -import { Note } from '../notes/note.entity'; -import { Tag } from '../notes/tag.entity'; -import { Edit } from './edit.entity'; - -/** - * The state of a note at a particular point in time, - * with the content at that time and the diff to the previous revision. - * - */ -@Entity() -export class Revision { - @PrimaryGeneratedColumn() - id: number; - - /** - * The patch from the previous revision to this one. - */ - @Column({ - type: 'text', - }) - patch: string; - - @Column({ - type: 'text', - }) - title: string; - - @Column({ - type: 'text', - }) - description: string; - - @ManyToMany((_) => Tag, (tag) => tag.revisions, { - eager: true, - cascade: true, - }) - @JoinTable() - tags: Promise; - - /** - * The note content at this revision. - */ - @Column({ - type: 'text', - }) - content: string; - - /** - * The length of the note content. - */ - @Column() - length: number; - - @Column('simple-array', { nullable: true }) - yjsStateVector: null | number[]; - - /** - * Date at which the revision was created. - */ - @CreateDateColumn() - createdAt: Date; - - /** - * Note this revision belongs to. - */ - @ManyToOne((_) => Note, (note) => note.revisions, { onDelete: 'CASCADE' }) - note: Promise; - - /** - * All edit objects which are used in the revision. - */ - @ManyToMany((_) => Edit, (edit) => edit.revisions) - @JoinTable() - edits: Promise; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - static create( - content: string, - patch: string, - note: Note, - yjsStateVector: number[] | null, - title: string, - description: string, - tags: Tag[], - ): Omit { - const newRevision = new Revision(); - newRevision.patch = patch; - newRevision.content = content; - newRevision.length = content.length; - newRevision.title = title; - newRevision.description = description; - newRevision.tags = Promise.resolve(tags); - newRevision.note = Promise.resolve(note); - newRevision.edits = Promise.resolve([]); - newRevision.yjsStateVector = yjsStateVector ?? null; - return newRevision; - } -} diff --git a/backend/src/revisions/revisions.service.spec.ts b/backend/src/revisions/revisions.service.spec.ts index 9537ba4e2..82d00e663 100644 --- a/backend/src/revisions/revisions.service.spec.ts +++ b/backend/src/revisions/revisions.service.spec.ts @@ -23,6 +23,7 @@ import { registerNoteConfig, } from '../config/mock/note.config.mock'; import { NoteConfig } from '../config/note.config'; +import { User } from '../database/user.entity'; import { NotInDBError } from '../errors/errors'; import { eventModuleConfig } from '../events'; import { Group } from '../groups/group.entity'; @@ -34,7 +35,6 @@ import { Tag } from '../notes/tag.entity'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; import { Session } from '../sessions/session.entity'; -import { User } from '../users/user.entity'; import { Edit } from './edit.entity'; import { EditService } from './edit.service'; import { Revision } from './revision.entity'; diff --git a/backend/src/seed.ts b/backend/src/seed.ts index eb1c831de..07c3020a0 100644 --- a/backend/src/seed.ts +++ b/backend/src/seed.ts @@ -9,6 +9,7 @@ import { DataSource } from 'typeorm'; import { ApiToken } from './api-token/api-token.entity'; import { Identity } from './auth/identity.entity'; import { Author } from './authors/author.entity'; +import { User } from './database/user.entity'; import { Group } from './groups/group.entity'; import { HistoryEntry } from './history/history-entry.entity'; import { MediaUpload } from './media/media-upload.entity'; @@ -20,7 +21,6 @@ import { NoteUserPermission } from './permissions/note-user-permission.entity'; import { Edit } from './revisions/edit.entity'; import { Revision } from './revisions/revision.entity'; import { Session } from './sessions/session.entity'; -import { User } from './users/user.entity'; import { hashPassword } from './utils/password'; /** diff --git a/backend/src/users/user.entity.ts b/backend/src/users/user.entity.ts deleted file mode 100644 index 4378174b7..000000000 --- a/backend/src/users/user.entity.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { - Column, - CreateDateColumn, - Entity, - ManyToMany, - OneToMany, - PrimaryGeneratedColumn, - UpdateDateColumn, -} from 'typeorm'; - -import { ApiToken } from '../api-token/api-token.entity'; -import { Identity } from '../auth/identity.entity'; -import { Author } from '../authors/author.entity'; -import { Group } from '../groups/group.entity'; -import { HistoryEntry } from '../history/history-entry.entity'; -import { MediaUpload } from '../media/media-upload.entity'; -import { Note } from '../notes/note.entity'; - -@Entity() -export class User { - @PrimaryGeneratedColumn() - id: number; - - @Column({ - unique: true, - }) - username: string; - - @Column() - displayName: string; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; - - @Column({ - nullable: true, - type: 'text', - }) - photo: string | null; - - @Column({ - nullable: true, - type: 'text', - }) - email: string | null; - - @OneToMany((_) => Note, (note) => note.owner) - ownedNotes: Promise; - - @OneToMany((_) => ApiToken, (apiToken) => apiToken.user) - apiTokens: Promise; - - @OneToMany((_) => Identity, (identity) => identity.user) - identities: Promise; - - @ManyToMany((_) => Group, (group) => group.members) - groups: Promise; - - @OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user) - historyEntries: Promise; - - @OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.user) - mediaUploads: Promise; - - @OneToMany(() => Author, (author) => author.user) - authors: Promise; - - // eslint-disable-next-line @typescript-eslint/no-empty-function - private constructor() {} - - public static create( - username: string, - displayName: string, - email?: string, - photoUrl?: string, - ): Omit { - const newUser = new User(); - newUser.username = username; - newUser.displayName = displayName; - newUser.photo = photoUrl ?? null; - newUser.email = email ?? null; - newUser.ownedNotes = Promise.resolve([]); - newUser.apiTokens = Promise.resolve([]); - newUser.identities = Promise.resolve([]); - newUser.groups = Promise.resolve([]); - newUser.historyEntries = Promise.resolve([]); - newUser.mediaUploads = Promise.resolve([]); - newUser.authors = Promise.resolve([]); - return newUser; - } -} diff --git a/backend/src/users/users.module.ts b/backend/src/users/users.module.ts index 050859ec6..027d0f14b 100644 --- a/backend/src/users/users.module.ts +++ b/backend/src/users/users.module.ts @@ -7,9 +7,9 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Identity } from '../auth/identity.entity'; +import { User } from '../database/user.entity'; import { LoggerModule } from '../logger/logger.module'; import { Session } from '../sessions/session.entity'; -import { User } from './user.entity'; import { UsersService } from './users.service'; @Module({ diff --git a/backend/src/users/users.service.spec.ts b/backend/src/users/users.service.spec.ts index 54b88b8ed..bd0219ae6 100644 --- a/backend/src/users/users.service.spec.ts +++ b/backend/src/users/users.service.spec.ts @@ -10,9 +10,9 @@ import { Repository } from 'typeorm'; import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; +import { User } from '../database/user.entity'; import { AlreadyInDBError, NotInDBError } from '../errors/errors'; import { LoggerModule } from '../logger/logger.module'; -import { User } from './user.entity'; import { UsersService } from './users.service'; describe('UsersService', () => { diff --git a/backend/src/users/users.service.ts b/backend/src/users/users.service.ts index 8dd7b4c9b..c00fa9d68 100644 --- a/backend/src/users/users.service.ts +++ b/backend/src/users/users.service.ts @@ -15,10 +15,10 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import AuthConfiguration, { AuthConfig } from '../config/auth.config'; +import { User } from '../database/user.entity'; import { AlreadyInDBError, NotInDBError } from '../errors/errors'; import { ConsoleLoggerService } from '../logger/console-logger.service'; import { UserRelationEnum } from './user-relation.enum'; -import { User } from './user.entity'; @Injectable() export class UsersService { diff --git a/backend/test/private-api/alias.e2e-spec.ts b/backend/test/private-api/alias.e2e-spec.ts index 946724fef..de4566067 100644 --- a/backend/test/private-api/alias.e2e-spec.ts +++ b/backend/test/private-api/alias.e2e-spec.ts @@ -6,8 +6,8 @@ import { AliasCreateDto, AliasUpdateDto } from '@hedgedoc/commons'; import request from 'supertest'; +import { User } from '../../src/database/user.entity'; import { Note } from '../../src/notes/note.entity'; -import { User } from '../../src/users/user.entity'; import { password1, password2, diff --git a/backend/test/private-api/history.e2e-spec.ts b/backend/test/private-api/history.e2e-spec.ts index d15f72890..4eb13d530 100644 --- a/backend/test/private-api/history.e2e-spec.ts +++ b/backend/test/private-api/history.e2e-spec.ts @@ -6,12 +6,12 @@ import request from 'supertest'; import { LocalService } from '../../src/auth/local/local.service'; +import { User } from '../../src/database/user.entity'; import { HistoryEntryImportDto } from '../../src/history/history-entry-import.dto'; import { HistoryEntry } from '../../src/history/history-entry.entity'; import { HistoryService } from '../../src/history/history.service'; import { Note } from '../../src/notes/note.entity'; import { NotesService } from '../../src/notes/notes.service'; -import { User } from '../../src/users/user.entity'; import { UsersService } from '../../src/users/users.service'; import { TestSetup, TestSetupBuilder } from '../test-setup'; diff --git a/backend/test/private-api/me.e2e-spec.ts b/backend/test/private-api/me.e2e-spec.ts index 16fc93abe..30fefb391 100644 --- a/backend/test/private-api/me.e2e-spec.ts +++ b/backend/test/private-api/me.e2e-spec.ts @@ -7,9 +7,9 @@ import { LoginUserInfoDto, ProviderType } from '@hedgedoc/commons'; import { promises as fs } from 'fs'; import request from 'supertest'; +import { User } from '../../src/database/user.entity'; import { NotInDBError } from '../../src/errors/errors'; import { Note } from '../../src/notes/note.entity'; -import { User } from '../../src/users/user.entity'; import { TestSetup, TestSetupBuilder } from '../test-setup'; describe('Me', () => { diff --git a/backend/test/private-api/media.e2e-spec.ts b/backend/test/private-api/media.e2e-spec.ts index ee6af4185..082b331dd 100644 --- a/backend/test/private-api/media.e2e-spec.ts +++ b/backend/test/private-api/media.e2e-spec.ts @@ -5,7 +5,7 @@ */ import { promises as fs } from 'fs'; import { join } from 'path'; -import { User } from 'src/users/user.entity'; +import { User } from 'src/database/user.entity'; import request from 'supertest'; import { ConsoleLoggerService } from '../../src/logger/console-logger.service'; diff --git a/backend/test/private-api/notes.e2e-spec.ts b/backend/test/private-api/notes.e2e-spec.ts index b9637311c..fabbe03d7 100644 --- a/backend/test/private-api/notes.e2e-spec.ts +++ b/backend/test/private-api/notes.e2e-spec.ts @@ -7,9 +7,9 @@ import { promises as fs } from 'fs'; import { join } from 'path'; import request from 'supertest'; +import { User } from '../../src/database/user.entity'; import { NotInDBError } from '../../src/errors/errors'; import { Group } from '../../src/groups/group.entity'; -import { User } from '../../src/users/user.entity'; import { TestSetup, TestSetupBuilder } from '../test-setup'; describe('Notes', () => { diff --git a/backend/test/public-api/me.e2e-spec.ts b/backend/test/public-api/me.e2e-spec.ts index 6e87d48b2..c6c82d0ea 100644 --- a/backend/test/public-api/me.e2e-spec.ts +++ b/backend/test/public-api/me.e2e-spec.ts @@ -6,11 +6,11 @@ import { NoteMetadataDto } from '@hedgedoc/commons'; import { promises as fs } from 'fs'; import { join } from 'path'; -import { HistoryEntryDto } from 'src/history/history-entry.dto'; import request from 'supertest'; +import { User } from '../../src/database/user.entity'; import { HistoryEntryUpdateDto } from '../../src/history/history-entry-update.dto'; -import { User } from '../../src/users/user.entity'; +import { HistoryEntryDto } from '../../src/history/history-entry.dto'; import { TestSetup, TestSetupBuilder } from '../test-setup'; describe('Me', () => { diff --git a/backend/test/test-setup.ts b/backend/test/test-setup.ts index 59270823f..63f6cffd1 100644 --- a/backend/test/test-setup.ts +++ b/backend/test/test-setup.ts @@ -60,6 +60,7 @@ import { registerNoteConfig, } from '../src/config/mock/note.config.mock'; import { NoteConfig } from '../src/config/note.config'; +import { User } from '../src/database/user.entity'; import { ErrorExceptionMapping } from '../src/errors/error-mapping'; import { eventModuleConfig } from '../src/events'; import { FrontendConfigModule } from '../src/frontend-config/frontend-config.module'; @@ -82,7 +83,6 @@ import { RevisionsModule } from '../src/revisions/revisions.module'; import { RevisionsService } from '../src/revisions/revisions.service'; import { SessionModule } from '../src/sessions/session.module'; import { SessionService } from '../src/sessions/session.service'; -import { User } from '../src/users/user.entity'; import { UsersModule } from '../src/users/users.module'; import { UsersService } from '../src/users/users.service'; diff --git a/yarn.lock b/yarn.lock index b06ea29b3..29e237e31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2512,13 +2512,6 @@ __metadata: languageName: node linkType: hard -"@gar/promisify@npm:^1.0.1": - version: 1.1.3 - resolution: "@gar/promisify@npm:1.1.3" - checksum: 10c0/0b3c9958d3cd17f4add3574975e3115ae05dc7f1298a60810414b16f6f558c137b5fb3cd3905df380bacfd955ec13f67c1e6710cbb5c246a7e8d65a8289b2bff - languageName: node - linkType: hard - "@hapi/hoek@npm:^9.0.0, @hapi/hoek@npm:^9.3.0": version: 9.3.0 resolution: "@hapi/hoek@npm:9.3.0" @@ -2554,11 +2547,11 @@ __metadata: "@nestjs/schematics": "npm:10.2.3" "@nestjs/swagger": "npm:8.0.7" "@nestjs/testing": "npm:10.4.15" - "@nestjs/typeorm": "npm:10.0.2" "@nestjs/websockets": "npm:10.4.15" "@node-rs/argon2": "npm:2.0.2" "@trivago/prettier-plugin-sort-imports": "npm:4.3.0" "@tsconfig/node18": "npm:18.2.4" + "@types/better-sqlite3": "npm:7.6.12" "@types/cli-color": "npm:2.0.6" "@types/cookie": "npm:1.0.0" "@types/cookie-signature": "npm:1.1.2" @@ -2580,10 +2573,10 @@ __metadata: "@zxcvbn-ts/language-common": "npm:3.0.4" "@zxcvbn-ts/language-en": "npm:3.0.2" base32-encode: "npm:1.2.0" + better-sqlite3: "npm:11.8.1" class-transformer: "npm:0.5.1" class-validator: "npm:0.14.1" cli-color: "npm:2.0.4" - connect-typeorm: "npm:2.0.0" cookie: "npm:1.0.2" diff: "npm:7.0.0" eslint: "npm:8.57.1" @@ -2596,11 +2589,13 @@ __metadata: file-type: "npm:16.5.4" htmlparser2: "npm:9.1.0" jest: "npm:29.7.0" + knex: "npm:3.1.0" ldapauth-fork: "npm:6.1.0" markdown-it: "npm:13.0.2" minio: "npm:8.0.4" mocked-env: "npm:1.3.5" mysql: "npm:2.18.1" + nestjs-knex: "npm:2.0.0" nestjs-zod: "npm:4.3.1" node-fetch: "npm:2.7.0" openid-client: "npm:5.7.1" @@ -2611,13 +2606,11 @@ __metadata: rimraf: "npm:6.0.1" rxjs: "npm:7.8.1" source-map-support: "npm:0.5.21" - sqlite3: "npm:5.1.7" supertest: "npm:6.3.4" ts-jest: "npm:29.2.5" ts-mockery: "npm:1.2.0" ts-node: "npm:11.0.0-beta.1" tsconfig-paths: "npm:4.2.0" - typeorm: "npm:0.3.20" typescript: "npm:5.6.3" uuid: "npm:11.0.5" ws: "npm:8.18.0" @@ -4009,21 +4002,6 @@ __metadata: languageName: node linkType: hard -"@nestjs/typeorm@npm:10.0.2": - version: 10.0.2 - resolution: "@nestjs/typeorm@npm:10.0.2" - dependencies: - uuid: "npm:9.0.1" - peerDependencies: - "@nestjs/common": ^8.0.0 || ^9.0.0 || ^10.0.0 - "@nestjs/core": ^8.0.0 || ^9.0.0 || ^10.0.0 - reflect-metadata: ^0.1.13 || ^0.2.0 - rxjs: ^7.2.0 - typeorm: ^0.3.0 - checksum: 10c0/0c5a59273cab43c5b7e4da189e6b9792b64309b32a09c7dbd4bcd6bf2e6ac58faeb3ae40067d3fe987ca857841031bf91c90416ae6824e3525e3e990eb5cf852 - languageName: node - linkType: hard - "@nestjs/websockets@npm:10.4.15": version: 10.4.15 resolution: "@nestjs/websockets@npm:10.4.15" @@ -4323,16 +4301,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/fs@npm:^1.0.0": - version: 1.1.1 - resolution: "@npmcli/fs@npm:1.1.1" - dependencies: - "@gar/promisify": "npm:^1.0.1" - semver: "npm:^7.3.5" - checksum: 10c0/4143c317a7542af9054018b71601e3c3392e6704e884561229695f099a71336cbd580df9a9ffb965d0024bf0ed593189ab58900fd1714baef1c9ee59c738c3e2 - languageName: node - linkType: hard - "@npmcli/fs@npm:^3.1.0": version: 3.1.0 resolution: "@npmcli/fs@npm:3.1.0" @@ -4342,16 +4310,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/move-file@npm:^1.0.1": - version: 1.1.2 - resolution: "@npmcli/move-file@npm:1.1.2" - dependencies: - mkdirp: "npm:^1.0.4" - rimraf: "npm:^3.0.2" - checksum: 10c0/02e946f3dafcc6743132fe2e0e2b585a96ca7265653a38df5a3e53fcf26c7c7a57fc0f861d7c689a23fdb6d6836c7eea5050c8086abf3c994feb2208d1514ff0 - languageName: node - linkType: hard - "@nuxtjs/opencollective@npm:0.3.2": version: 0.3.2 resolution: "@nuxtjs/opencollective@npm:0.3.2" @@ -4754,13 +4712,6 @@ __metadata: languageName: node linkType: hard -"@sqltools/formatter@npm:^1.2.5": - version: 1.2.5 - resolution: "@sqltools/formatter@npm:1.2.5" - checksum: 10c0/4b4fa62b8cd4880784b71cc5edd4a13da04fda0a915c14282765a8ec1a900a495e69b322704413e2052d221b5646d9fb0e20e87911f9a8f438f33180eecb11a4 - languageName: node - linkType: hard - "@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0": version: 8.0.0 resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0" @@ -5044,13 +4995,6 @@ __metadata: languageName: node linkType: hard -"@tootallnate/once@npm:1": - version: 1.1.2 - resolution: "@tootallnate/once@npm:1.1.2" - checksum: 10c0/8fe4d006e90422883a4fa9339dd05a83ff626806262e1710cee5758d493e8cbddf2db81c0e4690636dc840b02c9fda62877866ea774ebd07c1777ed5fafbdec6 - languageName: node - linkType: hard - "@tootallnate/once@npm:2": version: 2.0.0 resolution: "@tootallnate/once@npm:2.0.0" @@ -5177,6 +5121,15 @@ __metadata: languageName: node linkType: hard +"@types/better-sqlite3@npm:7.6.12": + version: 7.6.12 + resolution: "@types/better-sqlite3@npm:7.6.12" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/5367de7492e2c697aa20cc4024ba26210971d15f60c01ef691eddfbbfd39ccf9f80d5129fd7fd6c76c98804739325e23d2b156b0eac8f5a7665ba374a08ac1e7 + languageName: node + linkType: hard + "@types/body-parser@npm:*": version: 1.19.5 resolution: "@types/body-parser@npm:1.19.5" @@ -5553,13 +5506,6 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:0.0.31": - version: 0.0.31 - resolution: "@types/debug@npm:0.0.31" - checksum: 10c0/78d6b40801193af246028ce8841c384146b573572dbcec073413188acffa3573f6ce2cc9ecd5e72738467b0d67b6f7fd82b8c110cae861c6d7a9418d1e10d6ba - languageName: node - linkType: hard - "@types/diff@npm:6.0.0": version: 6.0.0 resolution: "@types/diff@npm:6.0.0" @@ -5634,7 +5580,7 @@ __metadata: languageName: node linkType: hard -"@types/express-session@npm:1.18.0, @types/express-session@npm:^1.15.5": +"@types/express-session@npm:1.18.0": version: 1.18.0 resolution: "@types/express-session@npm:1.18.0" dependencies: @@ -6897,13 +6843,6 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:1": - version: 1.1.1 - resolution: "abbrev@npm:1.1.1" - checksum: 10c0/3f762677702acb24f65e813070e306c61fafe25d4b2583f9dfc935131f774863f3addd5741572ed576bd69cabe473c5af18e1e108b829cb7b6b4747884f726e6 - languageName: node - linkType: hard - "abbrev@npm:^2.0.0": version: 2.0.0 resolution: "abbrev@npm:2.0.0" @@ -6988,7 +6927,7 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:6, agent-base@npm:^6.0.2": +"agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" dependencies: @@ -7006,15 +6945,6 @@ __metadata: languageName: node linkType: hard -"agentkeepalive@npm:^4.1.3": - version: 4.5.0 - resolution: "agentkeepalive@npm:4.5.0" - dependencies: - humanize-ms: "npm:^1.2.1" - checksum: 10c0/394ea19f9710f230722996e156607f48fdf3a345133b0b1823244b7989426c16019a428b56c82d3eabef616e938812981d9009f4792ecc66bd6a59e991c62612 - languageName: node - linkType: hard - "aggregate-error@npm:^3.0.0": version: 3.1.0 resolution: "aggregate-error@npm:3.1.0" @@ -7145,13 +7075,6 @@ __metadata: languageName: node linkType: hard -"any-promise@npm:^1.0.0": - version: 1.3.0 - resolution: "any-promise@npm:1.3.0" - checksum: 10c0/60f0298ed34c74fef50daab88e8dab786036ed5a7fad02e012ab57e376e0a0b4b29e83b95ea9b5e7d89df762f5f25119b83e00706ecaccb22cfbacee98d74889 - languageName: node - linkType: hard - "anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" @@ -7162,13 +7085,6 @@ __metadata: languageName: node linkType: hard -"app-root-path@npm:^3.1.0": - version: 3.1.0 - resolution: "app-root-path@npm:3.1.0" - checksum: 10c0/4a0fd976de1bffcdb18a5e1f8050091f15d0780e0582bca99aaa9d52de71f0e08e5185355fcffc781180bfb898499e787a2f5ed79b9c448b942b31dc947acaa9 - languageName: node - linkType: hard - "append-field@npm:^1.0.0": version: 1.0.0 resolution: "append-field@npm:1.0.0" @@ -7176,13 +7092,6 @@ __metadata: languageName: node linkType: hard -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: 10c0/d06e26384a8f6245d8c8896e138c0388824e259a329e0c9f196b4fa533c82502a6fd449586e3604950a0c42921832a458bb3aa0aa9f0ba449cfd4f50fd0d09b5 - languageName: node - linkType: hard - "arch@npm:^2.2.0": version: 2.2.0 resolution: "arch@npm:2.2.0" @@ -7190,16 +7099,6 @@ __metadata: languageName: node linkType: hard -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: "npm:^1.0.0" - readable-stream: "npm:^3.6.0" - checksum: 10c0/8373f289ba42e4b5ec713bb585acdac14b5702c75f2a458dc985b9e4fa5762bc5b46b40a21b72418a3ed0cfb5e35bdc317ef1ae132f3035f633d581dd03168c3 - languageName: node - linkType: hard - "arg@npm:^4.1.0": version: 4.1.3 resolution: "arg@npm:4.1.3" @@ -7692,6 +7591,17 @@ __metadata: languageName: node linkType: hard +"better-sqlite3@npm:11.8.1": + version: 11.8.1 + resolution: "better-sqlite3@npm:11.8.1" + dependencies: + bindings: "npm:^1.5.0" + node-gyp: "npm:latest" + prebuild-install: "npm:^7.1.1" + checksum: 10c0/b6b1844f8ed5668080cc1e2a137656da756af406b616ffbd6139b230c906b9c0571bbdac53cd78cc1415689f5090d25daf95ea596ced0b9ad5e8be9b4a08662e + languageName: node + linkType: hard + "bignumber.js@npm:9.0.0": version: 9.0.0 resolution: "bignumber.js@npm:9.0.0" @@ -7906,16 +7816,6 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^6.0.3": - version: 6.0.3 - resolution: "buffer@npm:6.0.3" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.2.1" - checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 - languageName: node - linkType: hard - "busboy@npm:1.6.0, busboy@npm:^1.0.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" @@ -7932,32 +7832,6 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^15.2.0": - version: 15.3.0 - resolution: "cacache@npm:15.3.0" - dependencies: - "@npmcli/fs": "npm:^1.0.0" - "@npmcli/move-file": "npm:^1.0.1" - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - glob: "npm:^7.1.4" - infer-owner: "npm:^1.0.4" - lru-cache: "npm:^6.0.0" - minipass: "npm:^3.1.1" - minipass-collect: "npm:^1.0.2" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.2" - mkdirp: "npm:^1.0.3" - p-map: "npm:^4.0.0" - promise-inflight: "npm:^1.0.1" - rimraf: "npm:^3.0.2" - ssri: "npm:^8.0.1" - tar: "npm:^6.0.2" - unique-filename: "npm:^1.1.1" - checksum: 10c0/886fcc0acc4f6fd5cd142d373d8276267bc6d655d7c4ce60726fbbec10854de3395ee19bbf9e7e73308cdca9fdad0ad55060ff3bd16c6d4165c5b8d21515e1d8 - languageName: node - linkType: hard - "cacache@npm:^18.0.0": version: 18.0.2 resolution: "cacache@npm:18.0.2" @@ -8248,22 +8122,6 @@ __metadata: languageName: node linkType: hard -"cli-highlight@npm:^2.1.11": - version: 2.1.11 - resolution: "cli-highlight@npm:2.1.11" - dependencies: - chalk: "npm:^4.0.0" - highlight.js: "npm:^10.7.1" - mz: "npm:^2.4.0" - parse5: "npm:^5.1.1" - parse5-htmlparser2-tree-adapter: "npm:^6.0.0" - yargs: "npm:^16.0.0" - bin: - highlight: bin/highlight - checksum: 10c0/b5b4af3b968aa9df77eee449a400fbb659cf47c4b03a395370bd98d5554a00afaa5819b41a9a8a1ca0d37b0b896a94e57c65289b37359a25b700b1f56eb04852 - languageName: node - linkType: hard - "cli-spinners@npm:^2.5.0": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" @@ -8328,17 +8186,6 @@ __metadata: languageName: node linkType: hard -"cliui@npm:^7.0.2": - version: 7.0.4 - resolution: "cliui@npm:7.0.4" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.0" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/6035f5daf7383470cef82b3d3db00bec70afb3423538c50394386ffbbab135e26c3689c41791f911fa71b62d13d3863c712fdd70f0fbdffd938a1e6fd09aac00 - languageName: node - linkType: hard - "cliui@npm:^8.0.1": version: 8.0.1 resolution: "cliui@npm:8.0.1" @@ -8428,15 +8275,6 @@ __metadata: languageName: node linkType: hard -"color-support@npm:^1.1.3": - version: 1.1.3 - resolution: "color-support@npm:1.1.3" - bin: - color-support: bin.js - checksum: 10c0/8ffeaa270a784dc382f62d9be0a98581db43e11eee301af14734a6d089bd456478b1a8b3e7db7ca7dc5b18a75f828f775c44074020b51c05fc00e6d0992b1cc6 - languageName: node - linkType: hard - "color@npm:^4.2.3": version: 4.2.3 resolution: "color@npm:4.2.3" @@ -8447,6 +8285,13 @@ __metadata: languageName: node linkType: hard +"colorette@npm:2.0.19": + version: 2.0.19 + resolution: "colorette@npm:2.0.19" + checksum: 10c0/2bcc9134095750fece6e88167011499b964b78bf0ea953469130ddb1dba3c8fe6c03debb0ae181e710e2be10900d117460f980483a7df4ba4a1bac3b182ecb64 + languageName: node + linkType: hard + "colorette@npm:^2.0.16": version: 2.0.20 resolution: "colorette@npm:2.0.20" @@ -8484,6 +8329,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^10.0.0": + version: 10.0.1 + resolution: "commander@npm:10.0.1" + checksum: 10c0/53f33d8927758a911094adadda4b2cbac111a5b377d8706700587650fd8f45b0bbe336de4b5c3fe47fd61f420a3d9bd452b6e0e6e5600a7e74d7bf0174f6efe3 + languageName: node + linkType: hard + "commander@npm:^6.2.1": version: 6.2.1 resolution: "commander@npm:6.2.1" @@ -8571,20 +8423,6 @@ __metadata: languageName: node linkType: hard -"connect-typeorm@npm:2.0.0": - version: 2.0.0 - resolution: "connect-typeorm@npm:2.0.0" - dependencies: - "@types/debug": "npm:0.0.31" - "@types/express-session": "npm:^1.15.5" - debug: "npm:^4.1.1" - express-session: "npm:^1.15.6" - peerDependencies: - typeorm: ^0.3.0 - checksum: 10c0/07ad91109804b4ff659752b3df31e0f467e48babc1abdbe2674ee6d64a3f0f645493414643947c4bdb8c317bebfca46197828951ee5844af5133c0dfc22bbfdd - languageName: node - linkType: hard - "consola@npm:^2.15.0": version: 2.15.3 resolution: "consola@npm:2.15.3" @@ -8592,13 +8430,6 @@ __metadata: languageName: node linkType: hard -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 10c0/7ab51d30b52d461412cd467721bb82afe695da78fff8f29fe6f6b9cbaac9a2328e27a22a966014df9532100f6dd85370460be8130b9c677891ba36d96a343f50 - languageName: node - linkType: hard - "content-disposition@npm:0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" @@ -8650,13 +8481,6 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.6.0": - version: 0.6.0 - resolution: "cookie@npm:0.6.0" - checksum: 10c0/f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 - languageName: node - linkType: hard - "cookie@npm:0.7.1": version: 0.7.1 resolution: "cookie@npm:0.7.1" @@ -9559,7 +9383,7 @@ __metadata: languageName: node linkType: hard -"dayjs@npm:^1.10.4, dayjs@npm:^1.11.9": +"dayjs@npm:^1.10.4": version: 1.11.10 resolution: "dayjs@npm:1.11.10" checksum: 10c0/4de9af50639d47df87f2e15fa36bb07e0f9ed1e9c52c6caa1482788ee9a384d668f1dbd00c54f82aaab163db07d61d2899384b8254da3a9184fc6deca080e2fe @@ -9589,7 +9413,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -9737,13 +9561,6 @@ __metadata: languageName: node linkType: hard -"delegates@npm:^1.0.0": - version: 1.0.0 - resolution: "delegates@npm:1.0.0" - checksum: 10c0/ba05874b91148e1db4bf254750c042bf2215febd23a6d3cda2e64896aef79745fbd4b9996488bd3cafb39ce19dbce0fd6e3b6665275638befffe1c9b312b91b5 - languageName: node - linkType: hard - "depd@npm:2.0.0, depd@npm:~2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" @@ -9967,7 +9784,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:16.4.5, dotenv@npm:^16.0.3, dotenv@npm:^16.3.0": +"dotenv@npm:16.4.5, dotenv@npm:^16.3.0": version: 16.4.5 resolution: "dotenv@npm:16.4.5" checksum: 10c0/48d92870076832af0418b13acd6e5a5a3e83bb00df690d9812e94b24aff62b88ade955ac99a05501305b8dc8f1b0ee7638b18493deb6fe93d680e5220936292f @@ -10089,7 +9906,7 @@ __metadata: languageName: node linkType: hard -"encoding@npm:^0.1.12, encoding@npm:^0.1.13": +"encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" dependencies: @@ -10898,6 +10715,13 @@ __metadata: languageName: node linkType: hard +"esm@npm:^3.2.25": + version: 3.2.25 + resolution: "esm@npm:3.2.25" + checksum: 10c0/8e60e8075506a7ce28681c30c8f54623fe18a251c364cd481d86719fc77f58aa055b293d80632d9686d5408aaf865ffa434897dc9fd9153c8b3f469fad23f094 + languageName: node + linkType: hard + "esniff@npm:^2.0.1": version: 2.0.1 resolution: "esniff@npm:2.0.1" @@ -11122,22 +10946,6 @@ __metadata: languageName: node linkType: hard -"express-session@npm:^1.15.6": - version: 1.18.0 - resolution: "express-session@npm:1.18.0" - dependencies: - cookie: "npm:0.6.0" - cookie-signature: "npm:1.0.7" - debug: "npm:2.6.9" - depd: "npm:~2.0.0" - on-headers: "npm:~1.0.2" - parseurl: "npm:~1.3.3" - safe-buffer: "npm:5.2.1" - uid-safe: "npm:~2.1.5" - checksum: 10c0/5c3f1237f2789cf32f9cd668d3217c228916edfd3b5a686a894a80c7cca63f9ef66bb86a8457074b9b4cc4b2ee97e16781dd4e0cff7829b671ab0db5da0db638 - languageName: node - linkType: hard - "express@npm:4.21.2": version: 4.21.2 resolution: "express@npm:4.21.2" @@ -11699,22 +11507,6 @@ __metadata: languageName: node linkType: hard -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: "npm:^1.0.3 || ^2.0.0" - color-support: "npm:^1.1.3" - console-control-strings: "npm:^1.1.0" - has-unicode: "npm:^2.0.1" - signal-exit: "npm:^3.0.7" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - wide-align: "npm:^1.1.5" - checksum: 10c0/ef10d7981113d69225135f994c9f8c4369d945e64a8fc721d655a3a38421b738c9fe899951721d1b47b73c41fdb5404ac87cc8903b2ecbed95d2800363e7e58c - languageName: node - linkType: hard - "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -11794,6 +11586,13 @@ __metadata: languageName: node linkType: hard +"getopts@npm:2.3.0": + version: 2.3.0 + resolution: "getopts@npm:2.3.0" + checksum: 10c0/edbcbd7020e9d87dc41e4ad9add5eb3873ae61339a62431bd92a461be2c0eaa9ec33b6fd0d67fa1b44feedffcf1cf28d6f9dbdb7d604cb1617eaba146a33cbca + languageName: node + linkType: hard + "getos@npm:^3.2.1": version: 3.2.1 resolution: "getos@npm:3.2.1" @@ -12087,13 +11886,6 @@ __metadata: languageName: node linkType: hard -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 10c0/ebdb2f4895c26bb08a8a100b62d362e49b2190bcfd84b76bc4be1a3bd4d254ec52d0dd9f2fbcc093fc5eb878b20c52146f9dfd33e2686ed28982187be593b47c - languageName: node - linkType: hard - "hasown@npm:^2.0.0, hasown@npm:^2.0.1": version: 2.0.1 resolution: "hasown@npm:2.0.1" @@ -12135,13 +11927,6 @@ __metadata: languageName: node linkType: hard -"highlight.js@npm:^10.7.1": - version: 10.7.3 - resolution: "highlight.js@npm:10.7.3" - checksum: 10c0/073837eaf816922427a9005c56c42ad8786473dc042332dfe7901aa065e92bc3d94ebf704975257526482066abb2c8677cc0326559bb8621e046c21c5991c434 - languageName: node - linkType: hard - "html-encoding-sniffer@npm:^3.0.0": version: 3.0.0 resolution: "html-encoding-sniffer@npm:3.0.0" @@ -12186,7 +11971,7 @@ __metadata: languageName: node linkType: hard -"http-cache-semantics@npm:^4.1.0, http-cache-semantics@npm:^4.1.1": +"http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc @@ -12206,17 +11991,6 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^4.0.1": - version: 4.0.1 - resolution: "http-proxy-agent@npm:4.0.1" - dependencies: - "@tootallnate/once": "npm:1" - agent-base: "npm:6" - debug: "npm:4" - checksum: 10c0/4fa4774d65b5331814b74ac05cefea56854fc0d5989c80b13432c1b0d42a14c9f4342ca3ad9f0359a52e78da12b1744c9f8a28e50042136ea9171675d972a5fd - languageName: node - linkType: hard - "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -12249,7 +12023,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^5.0.0, https-proxy-agent@npm:^5.0.1": +"https-proxy-agent@npm:^5.0.1": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" dependencies: @@ -12293,15 +12067,6 @@ __metadata: languageName: node linkType: hard -"humanize-ms@npm:^1.2.1": - version: 1.2.1 - resolution: "humanize-ms@npm:1.2.1" - dependencies: - ms: "npm:^2.0.0" - checksum: 10c0/f34a2c20161d02303c2807badec2f3b49cbfbbb409abd4f95a07377ae01cfe6b59e3d15ac609cffcd8f2521f0eb37b7e1091acf65da99aa2a4f1ad63c21e7e7a - languageName: node - linkType: hard - "hyphenate-style-name@npm:^1.0.3": version: 1.0.4 resolution: "hyphenate-style-name@npm:1.0.4" @@ -12425,13 +12190,6 @@ __metadata: languageName: node linkType: hard -"infer-owner@npm:^1.0.4": - version: 1.0.4 - resolution: "infer-owner@npm:1.0.4" - checksum: 10c0/a7b241e3149c26e37474e3435779487f42f36883711f198c45794703c7556bc38af224088bd4d1a221a45b8208ae2c2bcf86200383621434d0c099304481c5b9 - languageName: node - linkType: hard - "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -12442,7 +12200,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -12543,6 +12301,13 @@ __metadata: languageName: node linkType: hard +"interpret@npm:^2.2.0": + version: 2.2.0 + resolution: "interpret@npm:2.2.0" + checksum: 10c0/c0ef90daec6c4120bb7a226fa09a9511f6b5618aa9c94cf4641472f486948e643bb3b36efbd0136bbffdee876435af9fdf7bbb4622f5a16778eed5397f8a1946 + languageName: node + linkType: hard + "invariant@npm:^2.2.1, invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" @@ -13885,6 +13650,45 @@ __metadata: languageName: node linkType: hard +"knex@npm:3.1.0": + version: 3.1.0 + resolution: "knex@npm:3.1.0" + dependencies: + colorette: "npm:2.0.19" + commander: "npm:^10.0.0" + debug: "npm:4.3.4" + escalade: "npm:^3.1.1" + esm: "npm:^3.2.25" + get-package-type: "npm:^0.1.0" + getopts: "npm:2.3.0" + interpret: "npm:^2.2.0" + lodash: "npm:^4.17.21" + pg-connection-string: "npm:2.6.2" + rechoir: "npm:^0.8.0" + resolve-from: "npm:^5.0.0" + tarn: "npm:^3.0.2" + tildify: "npm:2.0.0" + peerDependenciesMeta: + better-sqlite3: + optional: true + mysql: + optional: true + mysql2: + optional: true + pg: + optional: true + pg-native: + optional: true + sqlite3: + optional: true + tedious: + optional: true + bin: + knex: bin/cli.js + checksum: 10c0/d8a1f99fad143c6057e94759b2ae700ae661a0b0b2385f643011962ef501dcc7b32cfdb5bda66ef81283ca56f13630f47691c579ce66ad0e8128e209533c3785 + languageName: node + linkType: hard + "kolorist@npm:^1.8.0": version: 1.8.0 resolution: "kolorist@npm:1.8.0" @@ -14294,30 +14098,6 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^9.1.0": - version: 9.1.0 - resolution: "make-fetch-happen@npm:9.1.0" - dependencies: - agentkeepalive: "npm:^4.1.3" - cacache: "npm:^15.2.0" - http-cache-semantics: "npm:^4.1.0" - http-proxy-agent: "npm:^4.0.1" - https-proxy-agent: "npm:^5.0.0" - is-lambda: "npm:^1.0.1" - lru-cache: "npm:^6.0.0" - minipass: "npm:^3.1.3" - minipass-collect: "npm:^1.0.2" - minipass-fetch: "npm:^1.3.2" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.2" - promise-retry: "npm:^2.0.1" - socks-proxy-agent: "npm:^6.0.0" - ssri: "npm:^8.0.0" - checksum: 10c0/2c737faf6a7f67077679da548b5bfeeef890595bf8c4323a1f76eae355d27ebb33dcf9cf1a673f944cf2f2a7cbf4e2b09f0a0a62931737728f210d902c6be966 - languageName: node - linkType: hard - "makeerror@npm:1.0.12": version: 1.0.12 resolution: "makeerror@npm:1.0.12" @@ -14782,15 +14562,6 @@ __metadata: languageName: node linkType: hard -"minipass-collect@npm:^1.0.2": - version: 1.0.2 - resolution: "minipass-collect@npm:1.0.2" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/8f82bd1f3095b24f53a991b04b67f4c710c894e518b813f0864a31de5570441a509be1ca17e0bb92b047591a8fdbeb886f502764fefb00d2f144f4011791e898 - languageName: node - linkType: hard - "minipass-collect@npm:^2.0.1": version: 2.0.1 resolution: "minipass-collect@npm:2.0.1" @@ -14800,21 +14571,6 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^1.3.2": - version: 1.4.1 - resolution: "minipass-fetch@npm:1.4.1" - dependencies: - encoding: "npm:^0.1.12" - minipass: "npm:^3.1.0" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.0.0" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a43da7401cd7c4f24b993887d41bd37d097356083b0bb836fd655916467463a1e6e9e553b2da4fcbe8745bf23d40c8b884eab20745562199663b3e9060cd8e7a - languageName: node - linkType: hard - "minipass-fetch@npm:^3.0.0": version: 3.0.4 resolution: "minipass-fetch@npm:3.0.4" @@ -14839,7 +14595,7 @@ __metadata: languageName: node linkType: hard -"minipass-pipeline@npm:^1.2.2, minipass-pipeline@npm:^1.2.4": +"minipass-pipeline@npm:^1.2.4": version: 1.2.4 resolution: "minipass-pipeline@npm:1.2.4" dependencies: @@ -14857,7 +14613,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^3.0.0, minipass@npm:^3.1.0, minipass@npm:^3.1.1, minipass@npm:^3.1.3": +"minipass@npm:^3.0.0": version: 3.3.6 resolution: "minipass@npm:3.3.6" dependencies: @@ -14887,7 +14643,7 @@ __metadata: languageName: node linkType: hard -"minizlib@npm:^2.0.0, minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": version: 2.1.2 resolution: "minizlib@npm:2.1.2" dependencies: @@ -14915,7 +14671,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": +"mkdirp@npm:^1.0.3": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" bin: @@ -14924,15 +14680,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^2.1.3": - version: 2.1.6 - resolution: "mkdirp@npm:2.1.6" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/96f551c651dd8f5f9435d53df1a7b9bfc553be769ee6da5192c37c1f303a376ef1c6996f96913d4a8d357060451d4526a346031d1919f92c58806a5fa3cd8dfe - languageName: node - linkType: hard - "mlly@npm:^1.4.2, mlly@npm:^1.7.1, mlly@npm:^1.7.2": version: 1.7.2 resolution: "mlly@npm:1.7.2" @@ -14978,7 +14725,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 @@ -15026,17 +14773,6 @@ __metadata: languageName: node linkType: hard -"mz@npm:^2.4.0": - version: 2.7.0 - resolution: "mz@npm:2.7.0" - dependencies: - any-promise: "npm:^1.0.0" - object-assign: "npm:^4.0.1" - thenify-all: "npm:^1.0.0" - checksum: 10c0/103114e93f87362f0b56ab5b2e7245051ad0276b646e3902c98397d18bb8f4a77f2ea4a2c9d3ad516034ea3a56553b60d3f5f78220001ca4c404bd711bd0af39 - languageName: node - linkType: hard - "nano-css@npm:^5.6.2": version: 5.6.2 resolution: "nano-css@npm:5.6.2" @@ -15079,7 +14815,7 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3, negotiator@npm:^0.6.2, negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 @@ -15093,6 +14829,17 @@ __metadata: languageName: node linkType: hard +"nestjs-knex@npm:2.0.0": + version: 2.0.0 + resolution: "nestjs-knex@npm:2.0.0" + peerDependencies: + "@nestjs/common": ">=6.7.0" + "@nestjs/core": ">=6.7.0" + knex: ">=0.95.4" + checksum: 10c0/8ce1e581aecf6f83f63adb82b41f2fd464e71657c9e01937fe026ea14d13672ce3bcc32b9066f2c62ac17a5285c908e049c8984b24d12288c0d82f9635d3703b + languageName: node + linkType: hard + "nestjs-zod@npm:4.3.1": version: 4.3.1 resolution: "nestjs-zod@npm:4.3.1" @@ -15240,26 +14987,6 @@ __metadata: languageName: node linkType: hard -"node-gyp@npm:8.x": - version: 8.4.1 - resolution: "node-gyp@npm:8.4.1" - dependencies: - env-paths: "npm:^2.2.0" - glob: "npm:^7.1.4" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^9.1.0" - nopt: "npm:^5.0.0" - npmlog: "npm:^6.0.0" - rimraf: "npm:^3.0.2" - semver: "npm:^7.3.5" - tar: "npm:^6.1.2" - which: "npm:^2.0.2" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/80ef333b3a882eb6a2695a8e08f31d618f4533eff192864e4a3a16b67ff0abc9d8c1d5fac0395550ec699326b9248c5e2b3be178492f7f4d1ccf97d2cf948021 - languageName: node - linkType: hard - "node-gyp@npm:latest": version: 10.0.1 resolution: "node-gyp@npm:10.0.1" @@ -15301,17 +15028,6 @@ __metadata: languageName: node linkType: hard -"nopt@npm:^5.0.0": - version: 5.0.0 - resolution: "nopt@npm:5.0.0" - dependencies: - abbrev: "npm:1" - bin: - nopt: bin/nopt.js - checksum: 10c0/fc5c4f07155cb455bf5fc3dd149fac421c1a40fd83c6bfe83aa82b52f02c17c5e88301321318adaa27611c8a6811423d51d29deaceab5fa158b585a61a551061 - languageName: node - linkType: hard - "nopt@npm:^7.0.0": version: 7.2.0 resolution: "nopt@npm:7.2.0" @@ -15339,18 +15055,6 @@ __metadata: languageName: node linkType: hard -"npmlog@npm:^6.0.0": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: "npm:^3.0.0" - console-control-strings: "npm:^1.1.0" - gauge: "npm:^4.0.3" - set-blocking: "npm:^2.0.0" - checksum: 10c0/0cacedfbc2f6139c746d9cd4a85f62718435ad0ca4a2d6459cd331dd33ae58206e91a0742c1558634efcde3f33f8e8e7fd3adf1bfe7978310cf00bd55cccf890 - languageName: node - linkType: hard - "nth-check@npm:^2.0.1": version: 2.1.1 resolution: "nth-check@npm:2.1.1" @@ -15367,7 +15071,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": +"object-assign@npm:^4, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 @@ -15705,29 +15409,6 @@ __metadata: languageName: node linkType: hard -"parse5-htmlparser2-tree-adapter@npm:^6.0.0": - version: 6.0.1 - resolution: "parse5-htmlparser2-tree-adapter@npm:6.0.1" - dependencies: - parse5: "npm:^6.0.1" - checksum: 10c0/dfa5960e2aaf125707e19a4b1bc333de49232eba5a6ffffb95d313a7d6087c3b7a274b58bee8d3bd41bdf150638815d1d601a42bbf2a0345208c3c35b1279556 - languageName: node - linkType: hard - -"parse5@npm:^5.1.1": - version: 5.1.1 - resolution: "parse5@npm:5.1.1" - checksum: 10c0/b0f87a77a7fea5f242e3d76917c983bbea47703b9371801d51536b78942db6441cbda174bf84eb30e47315ddc6f8a0b57d68e562c790154430270acd76c1fa03 - languageName: node - linkType: hard - -"parse5@npm:^6.0.1": - version: 6.0.1 - resolution: "parse5@npm:6.0.1" - checksum: 10c0/595821edc094ecbcfb9ddcb46a3e1fe3a718540f8320eff08b8cf6742a5114cce2d46d45f95c26191c11b184dcaf4e2960abcd9c5ed9eb9393ac9a37efcfdecb - languageName: node - linkType: hard - "parse5@npm:^7.0.0, parse5@npm:^7.1.1": version: 7.1.2 resolution: "parse5@npm:7.1.2" @@ -15879,6 +15560,13 @@ __metadata: languageName: node linkType: hard +"pg-connection-string@npm:2.6.2": + version: 2.6.2 + resolution: "pg-connection-string@npm:2.6.2" + checksum: 10c0/e8fdea74fcc8bdc3d7c5c6eadd9425fdba7e67fb7fe836f9c0cecad94c8984e435256657d1d8ce0483d1fedef667e7a57e32449a63cb805cb0289fc34b62da35 + languageName: node + linkType: hard + "pg-connection-string@npm:^2.7.0": version: 2.7.0 resolution: "pg-connection-string@npm:2.7.0" @@ -16271,13 +15959,6 @@ __metadata: languageName: node linkType: hard -"promise-inflight@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-inflight@npm:1.0.1" - checksum: 10c0/d179d148d98fbff3d815752fa9a08a87d3190551d1420f17c4467f628214db12235ae068d98cd001f024453676d8985af8f28f002345646c4ece4600a79620bc - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -16861,6 +16542,15 @@ __metadata: languageName: node linkType: hard +"rechoir@npm:^0.8.0": + version: 0.8.0 + resolution: "rechoir@npm:0.8.0" + dependencies: + resolve: "npm:^1.20.0" + checksum: 10c0/1a30074124a22abbd5d44d802dac26407fa72a0a95f162aa5504ba8246bc5452f8b1a027b154d9bdbabcd8764920ff9333d934c46a8f17479c8912e92332f3ff + languageName: node + linkType: hard + "redent@npm:^3.0.0": version: 3.0.0 resolution: "redent@npm:3.0.0" @@ -16894,13 +16584,6 @@ __metadata: languageName: node linkType: hard -"reflect-metadata@npm:^0.2.1": - version: 0.2.1 - resolution: "reflect-metadata@npm:0.2.1" - checksum: 10c0/6ca3c674bb43cf8ec3a3f5f38c8730a6116335f8e562fcdcdf3a492af168c5a7f0e8f17476a5710c3fe6bf9b5d22e8a463f14c0e26e326339cab65e099900ef7 - languageName: node - linkType: hard - "reflect.getprototypeof@npm:^1.0.4": version: 1.0.5 resolution: "reflect.getprototypeof@npm:1.0.5" @@ -17470,13 +17153,6 @@ __metadata: languageName: node linkType: hard -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454 - languageName: node - linkType: hard - "set-function-length@npm:^1.2.1": version: 1.2.1 resolution: "set-function-length@npm:1.2.1" @@ -17517,18 +17193,6 @@ __metadata: languageName: node linkType: hard -"sha.js@npm:^2.4.11": - version: 2.4.11 - resolution: "sha.js@npm:2.4.11" - dependencies: - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" - bin: - sha.js: ./bin.js - checksum: 10c0/b7a371bca8821c9cc98a0aeff67444a03d48d745cb103f17228b96793f455f0eb0a691941b89ea1e60f6359207e36081d9be193252b0f128e0daf9cfea2815a5 - languageName: node - linkType: hard - "sharp@npm:0.33.5": version: 0.33.5 resolution: "sharp@npm:0.33.5" @@ -17738,17 +17402,6 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^6.0.0": - version: 6.2.1 - resolution: "socks-proxy-agent@npm:6.2.1" - dependencies: - agent-base: "npm:^6.0.2" - debug: "npm:^4.3.3" - socks: "npm:^2.6.2" - checksum: 10c0/d75c1cf1fdd7f8309a43a77f84409b793fc0f540742ef915154e70ac09a08b0490576fe85d4f8d68bbf80e604a62957a17ab5ef50d312fe1442b0ab6f8f6e6f6 - languageName: node - linkType: hard - "socks-proxy-agent@npm:^8.0.1": version: 8.0.2 resolution: "socks-proxy-agent@npm:8.0.2" @@ -17760,7 +17413,7 @@ __metadata: languageName: node linkType: hard -"socks@npm:^2.6.2, socks@npm:^2.7.1": +"socks@npm:^2.7.1": version: 2.8.1 resolution: "socks@npm:2.8.1" dependencies: @@ -17853,27 +17506,6 @@ __metadata: languageName: node linkType: hard -"sqlite3@npm:5.1.7": - version: 5.1.7 - resolution: "sqlite3@npm:5.1.7" - dependencies: - bindings: "npm:^1.5.0" - node-addon-api: "npm:^7.0.0" - node-gyp: "npm:8.x" - prebuild-install: "npm:^7.1.1" - tar: "npm:^6.1.11" - peerDependencies: - node-gyp: 8.x - dependenciesMeta: - node-gyp: - optional: true - peerDependenciesMeta: - node-gyp: - optional: true - checksum: 10c0/10daab5d7854bd0ec3c7690c00359cd3444eabc869b68c68dcb61374a8fa5e2f4be06cf0aba78f7a16336d49e83e4631e8af98f8bd33c772fe8d60b45fa60bc1 - languageName: node - linkType: hard - "sqlstring@npm:2.3.1": version: 2.3.1 resolution: "sqlstring@npm:2.3.1" @@ -17911,15 +17543,6 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^8.0.0, ssri@npm:^8.0.1": - version: 8.0.1 - resolution: "ssri@npm:8.0.1" - dependencies: - minipass: "npm:^3.1.1" - checksum: 10c0/5cfae216ae02dcd154d1bbed2d0a60038a4b3a2fcaac3c7e47401ff4e058e551ee74cfdba618871bf168cd583db7b8324f94af6747d4303b73cd4c3f6dc5c9c2 - languageName: node - linkType: hard - "stack-generator@npm:^2.0.5": version: 2.0.10 resolution: "stack-generator@npm:2.0.10" @@ -18013,7 +17636,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -18404,7 +18027,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.2": +"tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.2.0 resolution: "tar@npm:6.2.0" dependencies: @@ -18418,6 +18041,13 @@ __metadata: languageName: node linkType: hard +"tarn@npm:^3.0.2": + version: 3.0.2 + resolution: "tarn@npm:3.0.2" + checksum: 10c0/ea2344e3d21936111176375bd6f34eba69a38ef1bc59434d523fd313166f8a28a47b0a847846c119f72dcf2c1e1231596d74ac3fcfc3cc73966b3d293a327269 + languageName: node + linkType: hard + "terser-webpack-plugin@npm:^5.3.10": version: 5.3.10 resolution: "terser-webpack-plugin@npm:5.3.10" @@ -18472,24 +18102,6 @@ __metadata: languageName: node linkType: hard -"thenify-all@npm:^1.0.0": - version: 1.6.0 - resolution: "thenify-all@npm:1.6.0" - dependencies: - thenify: "npm:>= 3.1.0 < 4" - checksum: 10c0/9b896a22735e8122754fe70f1d65f7ee691c1d70b1f116fda04fea103d0f9b356e3676cb789506e3909ae0486a79a476e4914b0f92472c2e093d206aed4b7d6b - languageName: node - linkType: hard - -"thenify@npm:>= 3.1.0 < 4": - version: 3.3.1 - resolution: "thenify@npm:3.3.1" - dependencies: - any-promise: "npm:^1.0.0" - checksum: 10c0/f375aeb2b05c100a456a30bc3ed07ef03a39cbdefe02e0403fb714b8c7e57eeaad1a2f5c4ecfb9ce554ce3db9c2b024eba144843cd9e344566d9fcee73b04767 - languageName: node - linkType: hard - "throttle-debounce@npm:^3.0.1": version: 3.0.1 resolution: "throttle-debounce@npm:3.0.1" @@ -18520,6 +18132,13 @@ __metadata: languageName: node linkType: hard +"tildify@npm:2.0.0": + version: 2.0.0 + resolution: "tildify@npm:2.0.0" + checksum: 10c0/57961810a6915f47bdba7da7fa66a5f12597a0495fa016785de197b02e7ba9994ffebb30569294061bbf6d9395c6b1319d830076221e5a3f49f1318bc749565c + languageName: node + linkType: hard + "timers-ext@npm:^0.1.7": version: 0.1.7 resolution: "timers-ext@npm:0.1.7" @@ -18887,7 +18506,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.2": +"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 10c0/e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb @@ -19126,86 +18745,6 @@ __metadata: languageName: node linkType: hard -"typeorm@npm:0.3.20": - version: 0.3.20 - resolution: "typeorm@npm:0.3.20" - dependencies: - "@sqltools/formatter": "npm:^1.2.5" - app-root-path: "npm:^3.1.0" - buffer: "npm:^6.0.3" - chalk: "npm:^4.1.2" - cli-highlight: "npm:^2.1.11" - dayjs: "npm:^1.11.9" - debug: "npm:^4.3.4" - dotenv: "npm:^16.0.3" - glob: "npm:^10.3.10" - mkdirp: "npm:^2.1.3" - reflect-metadata: "npm:^0.2.1" - sha.js: "npm:^2.4.11" - tslib: "npm:^2.5.0" - uuid: "npm:^9.0.0" - yargs: "npm:^17.6.2" - peerDependencies: - "@google-cloud/spanner": ^5.18.0 - "@sap/hana-client": ^2.12.25 - better-sqlite3: ^7.1.2 || ^8.0.0 || ^9.0.0 - hdb-pool: ^0.1.6 - ioredis: ^5.0.4 - mongodb: ^5.8.0 - mssql: ^9.1.1 || ^10.0.1 - mysql2: ^2.2.5 || ^3.0.1 - oracledb: ^6.3.0 - pg: ^8.5.1 - pg-native: ^3.0.0 - pg-query-stream: ^4.0.0 - redis: ^3.1.1 || ^4.0.0 - sql.js: ^1.4.0 - sqlite3: ^5.0.3 - ts-node: ^10.7.0 - typeorm-aurora-data-api-driver: ^2.0.0 - peerDependenciesMeta: - "@google-cloud/spanner": - optional: true - "@sap/hana-client": - optional: true - better-sqlite3: - optional: true - hdb-pool: - optional: true - ioredis: - optional: true - mongodb: - optional: true - mssql: - optional: true - mysql2: - optional: true - oracledb: - optional: true - pg: - optional: true - pg-native: - optional: true - pg-query-stream: - optional: true - redis: - optional: true - sql.js: - optional: true - sqlite3: - optional: true - ts-node: - optional: true - typeorm-aurora-data-api-driver: - optional: true - bin: - typeorm: cli.js - typeorm-ts-node-commonjs: cli-ts-node-commonjs.js - typeorm-ts-node-esm: cli-ts-node-esm.js - checksum: 10c0/7e4be724641beef86ae36289c87b6e66bfaf19a4313f089926d36d2d6f0d67f9314d942711c9d83ab8a174b8622148c2f7e83e6c1448d638ee3ab24469257814 - languageName: node - linkType: hard - "typescript@npm:5.6.3": version: 5.6.3 resolution: "typescript@npm:5.6.3" @@ -19372,15 +18911,6 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^1.1.1": - version: 1.1.1 - resolution: "unique-filename@npm:1.1.1" - dependencies: - unique-slug: "npm:^2.0.0" - checksum: 10c0/d005bdfaae6894da8407c4de2b52f38b3c58ec86e79fc2ee19939da3085374413b073478ec54e721dc8e32b102cf9e50d0481b8331abdc62202e774b789ea874 - languageName: node - linkType: hard - "unique-filename@npm:^3.0.0": version: 3.0.0 resolution: "unique-filename@npm:3.0.0" @@ -19390,15 +18920,6 @@ __metadata: languageName: node linkType: hard -"unique-slug@npm:^2.0.0": - version: 2.0.2 - resolution: "unique-slug@npm:2.0.2" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/9eabc51680cf0b8b197811a48857e41f1364b25362300c1ff636c0eca5ec543a92a38786f59cf0697e62c6f814b11ecbe64e8093db71246468a1f03b80c83970 - languageName: node - linkType: hard - "unique-slug@npm:^4.0.0": version: 4.0.0 resolution: "unique-slug@npm:4.0.0" @@ -19551,15 +19072,6 @@ __metadata: languageName: node linkType: hard -"uuid@npm:9.0.1, uuid@npm:^9.0.0, uuid@npm:^9.0.1": - version: 9.0.1 - resolution: "uuid@npm:9.0.1" - bin: - uuid: dist/bin/uuid - checksum: 10c0/1607dd32ac7fc22f2d8f77051e6a64845c9bce5cd3dd8aa0070c074ec73e666a1f63c7b4e0f4bf2bc8b9d59dc85a15e17807446d9d2b17c8485fbc2147b27f9b - languageName: node - linkType: hard - "uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" @@ -19569,6 +19081,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^9.0.1": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 10c0/1607dd32ac7fc22f2d8f77051e6a64845c9bce5cd3dd8aa0070c074ec73e666a1f63c7b4e0f4bf2bc8b9d59dc85a15e17807446d9d2b17c8485fbc2147b27f9b + languageName: node + linkType: hard + "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1" @@ -20419,7 +19940,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1, which@npm:^2.0.2": +"which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -20441,15 +19962,6 @@ __metadata: languageName: node linkType: hard -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" - dependencies: - string-width: "npm:^1.0.2 || 2 || 3 || 4" - checksum: 10c0/1d9c2a3e36dfb09832f38e2e699c367ef190f96b82c71f809bc0822c306f5379df87bab47bed27ea99106d86447e50eb972d3c516c2f95782807a9d082fbea95 - languageName: node - linkType: hard - "words-count@npm:2.0.2": version: 2.0.2 resolution: "words-count@npm:2.0.2" @@ -20625,14 +20137,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^20.2.2": - version: 20.2.9 - resolution: "yargs-parser@npm:20.2.9" - checksum: 10c0/0685a8e58bbfb57fab6aefe03c6da904a59769bd803a722bb098bd5b0f29d274a1357762c7258fb487512811b8063fb5d2824a3415a0a4540598335b3b086c72 - languageName: node - linkType: hard - -"yargs@npm:17.7.2, yargs@npm:^17.3.1, yargs@npm:^17.6.2, yargs@npm:~17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.3.1, yargs@npm:~17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: @@ -20647,21 +20152,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^16.0.0": - version: 16.2.0 - resolution: "yargs@npm:16.2.0" - dependencies: - cliui: "npm:^7.0.2" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.0" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^20.2.2" - checksum: 10c0/b1dbfefa679848442454b60053a6c95d62f2d2e21dd28def92b647587f415969173c6e99a0f3bab4f1b67ee8283bf735ebe3544013f09491186ba9e8a9a2b651 - languageName: node - linkType: hard - "yauzl@npm:^2.10.0": version: 2.10.0 resolution: "yauzl@npm:2.10.0"