Skip to content

Commit b7354b5

Browse files
committed
Refactor done
1 parent 772ad5f commit b7354b5

4 files changed

Lines changed: 96 additions & 73 deletions

File tree

src/domain/entities/note.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,28 @@ export interface Note {
8787
* Part of note entity used to create new note
8888
*/
8989
export type NoteCreationAttributes = Pick<Note, 'publicId' | 'content' | 'creatorId' | 'tools'>;
90+
91+
/**
92+
* Part of note Hierarchy
93+
*/
94+
export type NoteRow = {
95+
/**
96+
* Note id
97+
*/
98+
noteId: NoteInternalId;
99+
100+
/**
101+
* Note public id
102+
*/
103+
publicId: NotePublicId;
104+
105+
/**
106+
* Note content
107+
*/
108+
content: NoteContent;
109+
110+
/**
111+
* Parent note id
112+
*/
113+
parentId: NoteInternalId | null;
114+
};

src/domain/service/note.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Note, NoteInternalId, NotePublicId } from '@domain/entities/note.js';
1+
import type { Note, NoteContent, NoteInternalId, NotePublicId } from '@domain/entities/note.js';
22
import type NoteRepository from '@repository/note.repository.js';
33
import type NoteVisitsRepository from '@repository/noteVisits.repository.js';
44
import { createPublicId } from '@infrastructure/utils/id.js';
@@ -466,8 +466,58 @@ export default class NoteService {
466466
// If there is no ultimate parent, the provided noteId is the ultimate parent
467467
const rootNoteId = ultimateParent ?? noteId;
468468

469-
const noteHierarchy = await this.noteRepository.getNoteHierarchyByNoteId(rootNoteId);
469+
const notesRows = await this.noteRepository.getNoteRowByNoteId(rootNoteId);
470470

471-
return noteHierarchy;
471+
const notesMap = new Map<NoteInternalId, NoteHierarchy>();
472+
473+
let root: NoteHierarchy | null = null;
474+
475+
if (!notesRows || notesRows.length === 0) {
476+
return null;
477+
}
478+
// Step 1: Parse and initialize all notes
479+
notesRows.forEach((note) => {
480+
notesMap.set(note.noteId, {
481+
noteId: note.publicId,
482+
noteTitle: this.getTitleFromContent(note.content),
483+
childNotes: null,
484+
});
485+
});
486+
487+
// Step 2: Build hierarchy
488+
notesRows.forEach((note) => {
489+
if (note.parentId === null) {
490+
root = notesMap.get(note.noteId) ?? null;
491+
} else {
492+
const parent = notesMap.get(note.parentId);
493+
494+
if (parent) {
495+
// Initialize childNotes as an array if it's null
496+
if (parent.childNotes === null) {
497+
parent.childNotes = [];
498+
}
499+
parent.childNotes?.push(notesMap.get(note.noteId)!);
500+
}
501+
}
502+
});
503+
504+
return root;
472505
}
506+
507+
/**
508+
* Get the title of the note
509+
* @param content - content of the note
510+
* @returns the title of the note
511+
*/
512+
public getTitleFromContent(content: NoteContent): string {
513+
const limitCharsForNoteTitle = 50;
514+
const firstNoteBlock = content.blocks[0];
515+
const text = (firstNoteBlock?.data as { text?: string })?.text;
516+
517+
if (text === undefined || text.trim() === '') {
518+
return 'Untitled';
519+
}
520+
521+
return text.replace(/&nbsp;/g, ' ').slice(0, limitCharsForNoteTitle);
522+
};
473523
}

src/repository/note.repository.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { Note, NoteCreationAttributes, NoteInternalId, NotePublicId } from '@domain/entities/note.js';
2-
import type { NoteHierarchy } from '@domain/entities/NoteHierarchy.js';
1+
import type { Note, NoteCreationAttributes, NoteInternalId, NotePublicId, NoteRow } from '@domain/entities/note.js';
32
import type NoteStorage from '@repository/storage/note.storage.js';
43

54
/**
@@ -93,11 +92,11 @@ export default class NoteRepository {
9392
}
9493

9594
/**
96-
* Gets the Note tree by note id
95+
* Fetches the raw recursive note tree data from DB
9796
* @param noteId - note id
98-
* @returns NoteHierarchy structure
97+
* @returns Array of raw note rows (note with parent_id)
9998
*/
100-
public async getNoteHierarchyByNoteId(noteId: NoteInternalId): Promise<NoteHierarchy | null> {
101-
return await this.storage.getNoteHierarchybyNoteId(noteId);
99+
public async getNoteRowByNoteId(noteId: NoteInternalId): Promise<NoteRow[] | null> {
100+
return await this.storage.getNoteRowbyNoteId(noteId);
102101
}
103102
}

src/repository/storage/postgres/orm/sequelize/note.ts

Lines changed: 13 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import type { CreationOptional, InferAttributes, InferCreationAttributes, ModelStatic, NonAttribute, Sequelize } from 'sequelize';
22
import { DataTypes, Model, Op, QueryTypes } from 'sequelize';
33
import type Orm from '@repository/storage/postgres/orm/sequelize/index.js';
4-
import type { Note, NoteContent, NoteCreationAttributes, NoteInternalId, NotePublicId } from '@domain/entities/note.js';
4+
import type { Note, NoteCreationAttributes, NoteInternalId, NotePublicId, NoteRow } from '@domain/entities/note.js';
55
import { UserModel } from '@repository/storage/postgres/orm/sequelize/user.js';
66
import type { NoteSettingsModel } from './noteSettings.js';
77
import type { NoteVisitsModel } from './noteVisits.js';
88
import type { NoteHistoryModel } from './noteHistory.js';
9-
import type { NoteHierarchy } from '@domain/entities/NoteHierarchy.js';
109

1110
/* eslint-disable @typescript-eslint/naming-convention */
1211

@@ -349,33 +348,33 @@ export default class NoteSequelizeStorage {
349348
}
350349

351350
/**
352-
* Creates a tree of notes
353-
* @param noteId - public note id
354-
* @returns NoteHierarchy
351+
* Fetches the raw recursive note tree data from DB
352+
* @param noteId - note id
353+
* @returns Array of raw note rows (note with parent_id)
355354
*/
356-
public async getNoteHierarchybyNoteId(noteId: NoteInternalId): Promise<NoteHierarchy | null> {
355+
public async getNoteRowbyNoteId(noteId: NoteInternalId): Promise<NoteRow[] | null> {
357356
// Fetch all notes and relations in a recursive query
358357
const query = `
359358
WITH RECURSIVE note_tree AS (
360359
SELECT
361-
n.id AS noteId,
360+
n.id AS "noteId",
362361
n.content,
363-
n.public_id,
364-
nr.parent_id
362+
n.public_id AS "publicId",
363+
nr.parent_id AS "parentId"
365364
FROM ${String(this.database.literal(this.tableName).val)} n
366365
LEFT JOIN ${String(this.database.literal('note_relations').val)} nr ON n.id = nr.note_id
367366
WHERE n.id = :startNoteId
368367
369368
UNION ALL
370369
371370
SELECT
372-
n.id AS noteId,
371+
n.id AS "noteId",
373372
n.content,
374-
n.public_id,
375-
nr.parent_id
373+
n.public_id AS "publicId",
374+
nr.parent_id AS "parentId"
376375
FROM ${String(this.database.literal(this.tableName).val)} n
377376
INNER JOIN ${String(this.database.literal('note_relations').val)} nr ON n.id = nr.note_id
378-
INNER JOIN note_tree nt ON nr.parent_id = nt.noteId
377+
INNER JOIN note_tree nt ON nr.parent_id = nt."noteId"
379378
)
380379
SELECT * FROM note_tree;
381380
`;
@@ -388,58 +387,8 @@ export default class NoteSequelizeStorage {
388387
if (!result || result.length === 0) {
389388
return null; // No data found
390389
}
391-
392-
type NoteRow = {
393-
noteid: NoteInternalId;
394-
public_id: NotePublicId;
395-
content: NoteContent;
396-
parent_id: NoteInternalId | null;
397-
};
398-
399390
const notes = result as NoteRow[];
400391

401-
const notesMap = new Map<NoteInternalId, NoteHierarchy>();
402-
403-
let root: NoteHierarchy | null = null;
404-
405-
const getTitleFromContent = (content: NoteContent): string => {
406-
const limitCharsForNoteTitle = 50;
407-
const firstNoteBlock = content.blocks[0];
408-
const text = (firstNoteBlock?.data as { text?: string })?.text;
409-
410-
if (text === undefined || text.trim() === '') {
411-
return 'Untitled';
412-
}
413-
414-
return text.replace(/&nbsp;/g, ' ').slice(0, limitCharsForNoteTitle);
415-
};
416-
417-
// Step 1: Parse and initialize all notes
418-
notes.forEach((note) => {
419-
notesMap.set(note.noteid, {
420-
noteId: note.public_id,
421-
noteTitle: getTitleFromContent(note.content),
422-
childNotes: null,
423-
});
424-
});
425-
426-
// Step 2: Build hierarchy
427-
notes.forEach((note) => {
428-
if (note.parent_id === null) {
429-
root = notesMap.get(note.noteid) ?? null;
430-
} else {
431-
const parent = notesMap.get(note.parent_id);
432-
433-
if (parent) {
434-
// Initialize childNotes as an array if it's null
435-
if (parent.childNotes === null) {
436-
parent.childNotes = [];
437-
}
438-
parent.childNotes?.push(notesMap.get(note.noteid)!);
439-
}
440-
}
441-
});
442-
443-
return root;
392+
return notes;
444393
}
445394
}

0 commit comments

Comments
 (0)