refactor (backend): add note_file table to store (noteId, fileId) pairs
Co-authored-by: sup39 <dev@sup39.dev>
This commit is contained in:
parent
0f880b55e3
commit
2220d5c56e
16 changed files with 279 additions and 32 deletions
|
@ -1,6 +1,7 @@
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
DELETE FROM "migrations" WHERE name IN (
|
DELETE FROM "migrations" WHERE name IN (
|
||||||
|
'NoteFile1710304584214',
|
||||||
'RenameMetaColumns1705944717480',
|
'RenameMetaColumns1705944717480',
|
||||||
'SeparateHardMuteWordsAndPatterns1706413792769',
|
'SeparateHardMuteWordsAndPatterns1706413792769',
|
||||||
'IndexAltTextAndCw1708872574733',
|
'IndexAltTextAndCw1708872574733',
|
||||||
|
@ -16,6 +17,9 @@ DELETE FROM "migrations" WHERE name IN (
|
||||||
'RemoveNativeUtilsMigration1705877093218'
|
'RemoveNativeUtilsMigration1705877093218'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- note-file
|
||||||
|
DROP TABLE "note_file";
|
||||||
|
|
||||||
-- rename-meta-columns
|
-- rename-meta-columns
|
||||||
ALTER TABLE "meta" RENAME COLUMN "tosUrl" TO "ToSUrl";
|
ALTER TABLE "meta" RENAME COLUMN "tosUrl" TO "ToSUrl";
|
||||||
ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSsl" TO "objectStorageUseSSL";
|
ALTER TABLE "meta" RENAME COLUMN "objectStorageUseSsl" TO "objectStorageUseSSL";
|
||||||
|
|
|
@ -64,6 +64,8 @@ pub enum Relation {
|
||||||
DriveFolder,
|
DriveFolder,
|
||||||
#[sea_orm(has_many = "super::messaging_message::Entity")]
|
#[sea_orm(has_many = "super::messaging_message::Entity")]
|
||||||
MessagingMessage,
|
MessagingMessage,
|
||||||
|
#[sea_orm(has_many = "super::note_file::Entity")]
|
||||||
|
NoteFile,
|
||||||
#[sea_orm(has_many = "super::page::Entity")]
|
#[sea_orm(has_many = "super::page::Entity")]
|
||||||
Page,
|
Page,
|
||||||
#[sea_orm(
|
#[sea_orm(
|
||||||
|
@ -94,6 +96,12 @@ impl Related<super::messaging_message::Entity> for Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::note_file::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::NoteFile.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Related<super::page::Entity> for Entity {
|
impl Related<super::page::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
Relation::Page.def()
|
Relation::Page.def()
|
||||||
|
|
|
@ -35,6 +35,7 @@ pub mod muting;
|
||||||
pub mod note;
|
pub mod note;
|
||||||
pub mod note_edit;
|
pub mod note_edit;
|
||||||
pub mod note_favorite;
|
pub mod note_favorite;
|
||||||
|
pub mod note_file;
|
||||||
pub mod note_reaction;
|
pub mod note_reaction;
|
||||||
pub mod note_thread_muting;
|
pub mod note_thread_muting;
|
||||||
pub mod note_unread;
|
pub mod note_unread;
|
||||||
|
|
|
@ -100,6 +100,8 @@ pub enum Relation {
|
||||||
NoteEdit,
|
NoteEdit,
|
||||||
#[sea_orm(has_many = "super::note_favorite::Entity")]
|
#[sea_orm(has_many = "super::note_favorite::Entity")]
|
||||||
NoteFavorite,
|
NoteFavorite,
|
||||||
|
#[sea_orm(has_many = "super::note_file::Entity")]
|
||||||
|
NoteFile,
|
||||||
#[sea_orm(has_many = "super::note_reaction::Entity")]
|
#[sea_orm(has_many = "super::note_reaction::Entity")]
|
||||||
NoteReaction,
|
NoteReaction,
|
||||||
#[sea_orm(has_many = "super::note_unread::Entity")]
|
#[sea_orm(has_many = "super::note_unread::Entity")]
|
||||||
|
@ -164,6 +166,12 @@ impl Related<super::note_favorite::Entity> for Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Related<super::note_file::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::NoteFile.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Related<super::note_reaction::Entity> for Entity {
|
impl Related<super::note_reaction::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
Relation::NoteReaction.def()
|
Relation::NoteReaction.def()
|
||||||
|
|
48
packages/backend-rs/src/model/entity/note_file.rs
Normal file
48
packages/backend-rs/src/model/entity/note_file.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.12
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
|
#[sea_orm(table_name = "note_file")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(column_name = "serialNo", primary_key)]
|
||||||
|
pub serial_no: i64,
|
||||||
|
#[sea_orm(column_name = "noteId")]
|
||||||
|
pub note_id: String,
|
||||||
|
#[sea_orm(column_name = "fileId")]
|
||||||
|
pub file_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::drive_file::Entity",
|
||||||
|
from = "Column::FileId",
|
||||||
|
to = "super::drive_file::Column::Id",
|
||||||
|
on_update = "NoAction",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
DriveFile,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::note::Entity",
|
||||||
|
from = "Column::NoteId",
|
||||||
|
to = "super::note::Column::Id",
|
||||||
|
on_update = "NoAction",
|
||||||
|
on_delete = "Cascade"
|
||||||
|
)]
|
||||||
|
Note,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::drive_file::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::DriveFile.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::note::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Note.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -33,6 +33,7 @@ pub use super::muting::Entity as Muting;
|
||||||
pub use super::note::Entity as Note;
|
pub use super::note::Entity as Note;
|
||||||
pub use super::note_edit::Entity as NoteEdit;
|
pub use super::note_edit::Entity as NoteEdit;
|
||||||
pub use super::note_favorite::Entity as NoteFavorite;
|
pub use super::note_favorite::Entity as NoteFavorite;
|
||||||
|
pub use super::note_file::Entity as NoteFile;
|
||||||
pub use super::note_reaction::Entity as NoteReaction;
|
pub use super::note_reaction::Entity as NoteReaction;
|
||||||
pub use super::note_thread_muting::Entity as NoteThreadMuting;
|
pub use super::note_thread_muting::Entity as NoteThreadMuting;
|
||||||
pub use super::note_unread::Entity as NoteUnread;
|
pub use super::note_unread::Entity as NoteUnread;
|
||||||
|
|
|
@ -73,6 +73,7 @@ import { UserPending } from "@/models/entities/user-pending.js";
|
||||||
import { Webhook } from "@/models/entities/webhook.js";
|
import { Webhook } from "@/models/entities/webhook.js";
|
||||||
import { UserIp } from "@/models/entities/user-ip.js";
|
import { UserIp } from "@/models/entities/user-ip.js";
|
||||||
import { NoteEdit } from "@/models/entities/note-edit.js";
|
import { NoteEdit } from "@/models/entities/note-edit.js";
|
||||||
|
import { NoteFile } from "@/models/entities/note-file.js";
|
||||||
|
|
||||||
import { entities as charts } from "@/services/chart/entities.js";
|
import { entities as charts } from "@/services/chart/entities.js";
|
||||||
import { dbLogger } from "./logger.js";
|
import { dbLogger } from "./logger.js";
|
||||||
|
@ -143,6 +144,7 @@ export const entities = [
|
||||||
Note,
|
Note,
|
||||||
NoteEdit,
|
NoteEdit,
|
||||||
NoteFavorite,
|
NoteFavorite,
|
||||||
|
NoteFile,
|
||||||
NoteReaction,
|
NoteReaction,
|
||||||
NoteWatching,
|
NoteWatching,
|
||||||
NoteThreadMuting,
|
NoteThreadMuting,
|
||||||
|
|
41
packages/backend/src/migration/1710304584214-note-file.ts
Normal file
41
packages/backend/src/migration/1710304584214-note-file.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class NoteFile1710304584214 implements MigrationInterface {
|
||||||
|
name = "NoteFile1710304584214";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "note_file" (
|
||||||
|
"serialNo" bigserial PRIMARY KEY,
|
||||||
|
"noteId" varchar(32) NOT NULL,
|
||||||
|
"fileId" varchar(32) NOT NULL
|
||||||
|
)`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`
|
||||||
|
INSERT INTO "note_file" ("noteId", "fileId")
|
||||||
|
SELECT "t"."id", "t"."fid" FROM (
|
||||||
|
SELECT ROW_NUMBER() OVER () AS "rn", * FROM (
|
||||||
|
SELECT "id", UNNEST("fileIds") AS "fid" FROM "note"
|
||||||
|
)
|
||||||
|
) AS "t"
|
||||||
|
INNER JOIN "drive_file" ON "drive_file"."id" = "t"."fid"
|
||||||
|
ORDER BY "rn"
|
||||||
|
`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "note_file" ADD FOREIGN KEY ("noteId") REFERENCES "note" ("id") ON DELETE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "note_file" ADD FOREIGN KEY ("fileId") REFERENCES "drive_file" ("id") ON DELETE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE INDEX "IDX_note_file_noteId" ON "note_file" ("noteId")`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE INDEX "IDX_note_file_fileId" ON "note_file" ("fileId")`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "note_file"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ import { packedQueueCountSchema } from "@/models/schema/queue.js";
|
||||||
import { packedGalleryPostSchema } from "@/models/schema/gallery-post.js";
|
import { packedGalleryPostSchema } from "@/models/schema/gallery-post.js";
|
||||||
import { packedEmojiSchema } from "@/models/schema/emoji.js";
|
import { packedEmojiSchema } from "@/models/schema/emoji.js";
|
||||||
import { packedNoteEdit } from "@/models/schema/note-edit.js";
|
import { packedNoteEdit } from "@/models/schema/note-edit.js";
|
||||||
|
import { packedNoteFileSchema } from "@/models/schema/note-file.js";
|
||||||
|
|
||||||
export const refs = {
|
export const refs = {
|
||||||
UserLite: packedUserLiteSchema,
|
UserLite: packedUserLiteSchema,
|
||||||
|
@ -47,6 +48,7 @@ export const refs = {
|
||||||
App: packedAppSchema,
|
App: packedAppSchema,
|
||||||
MessagingMessage: packedMessagingMessageSchema,
|
MessagingMessage: packedMessagingMessageSchema,
|
||||||
Note: packedNoteSchema,
|
Note: packedNoteSchema,
|
||||||
|
NoteFile: packedNoteFileSchema,
|
||||||
NoteEdit: packedNoteEdit,
|
NoteEdit: packedNoteEdit,
|
||||||
NoteReaction: packedNoteReactionSchema,
|
NoteReaction: packedNoteReactionSchema,
|
||||||
NoteFavorite: packedNoteFavoriteSchema,
|
NoteFavorite: packedNoteFavoriteSchema,
|
||||||
|
|
|
@ -4,12 +4,17 @@ import {
|
||||||
Index,
|
Index,
|
||||||
JoinColumn,
|
JoinColumn,
|
||||||
Column,
|
Column,
|
||||||
|
ManyToMany,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
type Relation,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
|
import { Note } from "./note.js";
|
||||||
import { User } from "./user.js";
|
import { User } from "./user.js";
|
||||||
import { DriveFolder } from "./drive-folder.js";
|
import { DriveFolder } from "./drive-folder.js";
|
||||||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||||
|
import { NoteFile } from "./note-file.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index(["userId", "folderId", "id"])
|
@Index(["userId", "folderId", "id"])
|
||||||
|
@ -31,12 +36,6 @@ export class DriveFile {
|
||||||
})
|
})
|
||||||
public userId: User["id"] | null;
|
public userId: User["id"] | null;
|
||||||
|
|
||||||
@ManyToOne((type) => User, {
|
|
||||||
onDelete: "SET NULL",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public user: User | null;
|
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: 512,
|
||||||
|
@ -171,12 +170,6 @@ export class DriveFile {
|
||||||
})
|
})
|
||||||
public folderId: DriveFolder["id"] | null;
|
public folderId: DriveFolder["id"] | null;
|
||||||
|
|
||||||
@ManyToOne((type) => DriveFolder, {
|
|
||||||
onDelete: "SET NULL",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public folder: DriveFolder | null;
|
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column("boolean", {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -205,4 +198,30 @@ export class DriveFile {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public requestIp: string | null;
|
public requestIp: string | null;
|
||||||
|
|
||||||
|
//#region Relations
|
||||||
|
@OneToMany(
|
||||||
|
() => NoteFile,
|
||||||
|
(noteFile: NoteFile) => noteFile.file,
|
||||||
|
)
|
||||||
|
public noteFiles: Relation<NoteFile[]>;
|
||||||
|
|
||||||
|
@ManyToMany(
|
||||||
|
() => Note,
|
||||||
|
(note: Note) => note.files,
|
||||||
|
)
|
||||||
|
public notes: Relation<Note[]>;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, {
|
||||||
|
onDelete: "SET NULL",
|
||||||
|
})
|
||||||
|
@JoinColumn()
|
||||||
|
public user: User | null;
|
||||||
|
|
||||||
|
@ManyToOne(() => DriveFolder, {
|
||||||
|
onDelete: "SET NULL",
|
||||||
|
})
|
||||||
|
@JoinColumn()
|
||||||
|
public folder: DriveFolder | null;
|
||||||
|
//#endregion Relations
|
||||||
}
|
}
|
||||||
|
|
45
packages/backend/src/models/entities/note-file.ts
Normal file
45
packages/backend/src/models/entities/note-file.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
Index,
|
||||||
|
Column,
|
||||||
|
ManyToOne,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
type Relation,
|
||||||
|
} from "typeorm";
|
||||||
|
import { Note } from "./note.js";
|
||||||
|
import { DriveFile } from "./drive-file.js";
|
||||||
|
import { id } from "../id.js";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class NoteFile {
|
||||||
|
@PrimaryGeneratedColumn("increment")
|
||||||
|
public serialNo: number;
|
||||||
|
|
||||||
|
@Index("IDX_note_file_noteId", { unique: false })
|
||||||
|
@Column({
|
||||||
|
...id(),
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public noteId: Note["id"];
|
||||||
|
|
||||||
|
@Index("IDX_note_file_fileId", { unique: false })
|
||||||
|
@Column({
|
||||||
|
...id(),
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public fileId: DriveFile["id"];
|
||||||
|
|
||||||
|
//#region Relations
|
||||||
|
@ManyToOne(
|
||||||
|
() => Note,
|
||||||
|
(note: Note) => note.noteFiles,
|
||||||
|
)
|
||||||
|
public note: Relation<Note>;
|
||||||
|
|
||||||
|
@ManyToOne(
|
||||||
|
() => DriveFile,
|
||||||
|
(file: DriveFile) => file.noteFiles,
|
||||||
|
)
|
||||||
|
public file: Relation<DriveFile>;
|
||||||
|
//#endregion Relations
|
||||||
|
}
|
|
@ -2,15 +2,20 @@ import {
|
||||||
Entity,
|
Entity,
|
||||||
Index,
|
Index,
|
||||||
JoinColumn,
|
JoinColumn,
|
||||||
|
JoinTable,
|
||||||
Column,
|
Column,
|
||||||
PrimaryColumn,
|
PrimaryColumn,
|
||||||
|
ManyToMany,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
type Relation,
|
||||||
} from "typeorm";
|
} from "typeorm";
|
||||||
import { User } from "./user.js";
|
import { User } from "./user.js";
|
||||||
import type { DriveFile } from "./drive-file.js";
|
import { DriveFile } from "./drive-file.js";
|
||||||
import { id } from "../id.js";
|
import { id } from "../id.js";
|
||||||
import { noteVisibilities } from "../../types.js";
|
import { noteVisibilities } from "../../types.js";
|
||||||
import { Channel } from "./channel.js";
|
import { Channel } from "./channel.js";
|
||||||
|
import { NoteFile } from "./note-file.js";
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index("IDX_NOTE_TAGS", { synchronize: false })
|
@Index("IDX_NOTE_TAGS", { synchronize: false })
|
||||||
|
@ -34,12 +39,6 @@ export class Note {
|
||||||
})
|
})
|
||||||
public replyId: Note["id"] | null;
|
public replyId: Note["id"] | null;
|
||||||
|
|
||||||
@ManyToOne((type) => Note, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public reply: Note | null;
|
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
|
@ -48,12 +47,6 @@ export class Note {
|
||||||
})
|
})
|
||||||
public renoteId: Note["id"] | null;
|
public renoteId: Note["id"] | null;
|
||||||
|
|
||||||
@ManyToOne((type) => Note, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public renote: Note | null;
|
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: 256,
|
||||||
|
@ -93,12 +86,6 @@ export class Note {
|
||||||
})
|
})
|
||||||
public userId: User["id"];
|
public userId: User["id"];
|
||||||
|
|
||||||
@ManyToOne((type) => User, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public user: User | null;
|
|
||||||
|
|
||||||
@Column("boolean", {
|
@Column("boolean", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
|
@ -152,6 +139,7 @@ export class Note {
|
||||||
public score: number;
|
public score: number;
|
||||||
|
|
||||||
// FIXME: file id is not removed from this array even if the file is deleted
|
// FIXME: file id is not removed from this array even if the file is deleted
|
||||||
|
// TODO: drop this column and use note_files
|
||||||
@Index()
|
@Index()
|
||||||
@Column({
|
@Column({
|
||||||
...id(),
|
...id(),
|
||||||
|
@ -218,12 +206,55 @@ export class Note {
|
||||||
})
|
})
|
||||||
public channelId: Channel["id"] | null;
|
public channelId: Channel["id"] | null;
|
||||||
|
|
||||||
@ManyToOne((type) => Channel, {
|
//#region Relations
|
||||||
|
@OneToMany(
|
||||||
|
() => NoteFile,
|
||||||
|
(noteFile: NoteFile) => noteFile.note,
|
||||||
|
)
|
||||||
|
public noteFiles: Relation<NoteFile[]>;
|
||||||
|
|
||||||
|
@ManyToMany(
|
||||||
|
() => DriveFile,
|
||||||
|
(file: DriveFile) => file.notes,
|
||||||
|
)
|
||||||
|
@JoinTable({
|
||||||
|
name: "note_file",
|
||||||
|
joinColumn: {
|
||||||
|
name: "noteId",
|
||||||
|
referencedColumnName: "id",
|
||||||
|
},
|
||||||
|
inverseJoinColumn: {
|
||||||
|
name: "fileId",
|
||||||
|
referencedColumnName: "id",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
public files: Relation<DriveFile[]>;
|
||||||
|
|
||||||
|
@ManyToOne(() => Note, {
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
})
|
||||||
|
@JoinColumn()
|
||||||
|
public reply: Note | null;
|
||||||
|
|
||||||
|
@ManyToOne(() => Note, {
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
})
|
||||||
|
@JoinColumn()
|
||||||
|
public renote: Note | null;
|
||||||
|
|
||||||
|
@ManyToOne(() => Channel, {
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public channel: Channel | null;
|
public channel: Channel | null;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, {
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
})
|
||||||
|
@JoinColumn()
|
||||||
|
public user: User | null;
|
||||||
|
//#endregion Relations
|
||||||
|
|
||||||
//#region Denormalized fields
|
//#region Denormalized fields
|
||||||
@Index()
|
@Index()
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
|
|
|
@ -66,12 +66,14 @@ import { InstanceRepository } from "./repositories/instance.js";
|
||||||
import { Webhook } from "./entities/webhook.js";
|
import { Webhook } from "./entities/webhook.js";
|
||||||
import { UserIp } from "./entities/user-ip.js";
|
import { UserIp } from "./entities/user-ip.js";
|
||||||
import { NoteEdit } from "./entities/note-edit.js";
|
import { NoteEdit } from "./entities/note-edit.js";
|
||||||
|
import { NoteFileRepository } from "./repositories/note-file.js";
|
||||||
|
|
||||||
export const Announcements = db.getRepository(Announcement);
|
export const Announcements = db.getRepository(Announcement);
|
||||||
export const AnnouncementReads = db.getRepository(AnnouncementRead);
|
export const AnnouncementReads = db.getRepository(AnnouncementRead);
|
||||||
export const Apps = AppRepository;
|
export const Apps = AppRepository;
|
||||||
export const Notes = NoteRepository;
|
export const Notes = NoteRepository;
|
||||||
export const NoteEdits = db.getRepository(NoteEdit);
|
export const NoteEdits = db.getRepository(NoteEdit);
|
||||||
|
export const NoteFiles = NoteFileRepository;
|
||||||
export const NoteFavorites = NoteFavoriteRepository;
|
export const NoteFavorites = NoteFavoriteRepository;
|
||||||
export const NoteWatchings = db.getRepository(NoteWatching);
|
export const NoteWatchings = db.getRepository(NoteWatching);
|
||||||
export const NoteThreadMutings = db.getRepository(NoteThreadMuting);
|
export const NoteThreadMutings = db.getRepository(NoteThreadMuting);
|
||||||
|
|
4
packages/backend/src/models/repositories/note-file.ts
Normal file
4
packages/backend/src/models/repositories/note-file.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { db } from "@/db/postgre.js";
|
||||||
|
import { NoteFile } from "@/models/entities/note-file.js";
|
||||||
|
|
||||||
|
export const NoteFileRepository = db.getRepository(NoteFile).extend({});
|
24
packages/backend/src/models/schema/note-file.ts
Normal file
24
packages/backend/src/models/schema/note-file.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
export const packedNoteFileSchema = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
serialNo: {
|
||||||
|
type: "number",
|
||||||
|
optional: false,
|
||||||
|
nullable: false,
|
||||||
|
},
|
||||||
|
noteId: {
|
||||||
|
type: "string",
|
||||||
|
optional: false,
|
||||||
|
nullable: false,
|
||||||
|
format: "id",
|
||||||
|
example: "xxxxxxxxxx",
|
||||||
|
},
|
||||||
|
fileId: {
|
||||||
|
type: "string",
|
||||||
|
optional: false,
|
||||||
|
nullable: false,
|
||||||
|
format: "id",
|
||||||
|
example: "xxxxxxxxxx",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
|
@ -31,6 +31,7 @@ import {
|
||||||
Channels,
|
Channels,
|
||||||
ChannelFollowings,
|
ChannelFollowings,
|
||||||
NoteThreadMutings,
|
NoteThreadMutings,
|
||||||
|
NoteFiles,
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import type { App } from "@/models/entities/app.js";
|
import type { App } from "@/models/entities/app.js";
|
||||||
|
@ -343,6 +344,12 @@ export default async (
|
||||||
|
|
||||||
const note = await insertNote(user, data, tags, emojis, mentionedUsers);
|
const note = await insertNote(user, data, tags, emojis, mentionedUsers);
|
||||||
|
|
||||||
|
await NoteFiles.insert(
|
||||||
|
note.fileIds.map((fileId) => ({ noteId: note.id, fileId })),
|
||||||
|
).catch((e) => {
|
||||||
|
logger.error(inspect(e));
|
||||||
|
});
|
||||||
|
|
||||||
res(note);
|
res(note);
|
||||||
|
|
||||||
// Register host
|
// Register host
|
||||||
|
|
Loading…
Reference in a new issue