server-ts: Fix more errors in becca entities

This commit is contained in:
Elian Doran 2024-02-17 11:13:53 +02:00
parent 9aec3390dd
commit 3a20bef1a9
No known key found for this signature in database
9 changed files with 49 additions and 47 deletions

View File

@ -273,7 +273,7 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
*
* This is a low-level method, for notes and branches use `note.deleteNote()` and 'branch.deleteBranch()` instead.
*/
markAsDeleted(deleteId = null) {
markAsDeleted(deleteId: string | null = null) {
const constructorData = (this.constructor as unknown as ConstructorData<T>);
const entityId = (this as any)[constructorData.primaryKeyName];
const entityName = constructorData.entityName;

View File

@ -36,7 +36,7 @@ class BAttachment extends AbstractBeccaEntity<BAttachment> {
noteId?: number;
attachmentId?: string;
/** either noteId or revisionId to which this attachment belongs */
ownerId: string;
ownerId?: string;
role: string;
mime: string;
title: string;

View File

@ -7,6 +7,10 @@ import promotedAttributeDefinitionParser = require('../../services/promoted_attr
import sanitizeAttributeName = require('../../services/sanitize_attribute_name');
import { AttributeRow, AttributeType } from './rows.js';
interface SavingOpts {
skipValidation?: boolean;
}
/**
* Attribute is an abstract concept which has two real uses - label (key - value pair)
* and relation (representing named relationship between source and target note)
@ -174,7 +178,7 @@ class BAttribute extends AbstractBeccaEntity<BAttribute> {
return !(this.attributeId in this.becca.attributes);
}
beforeSaving(opts = {}) {
beforeSaving(opts: SavingOpts = {}) {
if (!opts.skipValidation) {
this.validate();
}

View File

@ -83,18 +83,18 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
}
const parentNote = this.parentNote;
if (!childNote.parents.includes(parentNote)) {
childNote.parents.push(parentNote);
}
if (!parentNote.children.includes(childNote)) {
parentNote.children.push(childNote);
if (parentNote) {
if (!childNote.parents.includes(parentNote)) {
childNote.parents.push(parentNote);
}
if (!parentNote.children.includes(childNote)) {
parentNote.children.push(childNote);
}
}
}
/** @returns {BNote} */
get childNote() {
get childNote(): BNote {
if (!(this.noteId in this.becca.notes)) {
// entities can come out of order in sync/import, create skeleton which will be filled later
this.becca.addNote(this.noteId, new BNote({noteId: this.noteId}));
@ -103,13 +103,12 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
return this.becca.notes[this.noteId];
}
/** @returns {BNote} */
getNote() {
getNote(): BNote {
return this.childNote;
}
/** @returns {BNote|undefined} - root branch will have undefined parent, all other branches have to have a parent note */
get parentNote() {
/** @returns root branch will have undefined parent, all other branches have to have a parent note */
get parentNote(): BNote | undefined {
if (!(this.parentNoteId in this.becca.notes) && this.parentNoteId !== 'none') {
// entities can come out of order in sync/import, create skeleton which will be filled later
this.becca.addNote(this.parentNoteId, new BNote({noteId: this.parentNoteId}));
@ -119,7 +118,7 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
}
get isDeleted() {
return !(this.branchId in this.becca.branches);
return (this.branchId == undefined || !(this.branchId in this.becca.branches));
}
/**

View File

@ -64,15 +64,16 @@ class BNote extends AbstractBeccaEntity<BNote> {
isBeingDeleted!: boolean;
isDecrypted!: boolean;
ownedAttributes!: BAttribute[];
parentBranches!: BBranch[];
parents!: BNote[];
children!: BNote[];
targetRelations!: BAttribute[];
private __flatTextCache!: string | null;
private parentBranches!: BBranch[];
private parents!: BNote[];
private children!: BNote[];
private ownedAttributes!: BAttribute[];
private __attributeCache!: BAttribute[] | null;
private __inheritableAttributeCache!: BAttribute[] | null;
private targetRelations!: BAttribute[];
private __ancestorCache!: BNote[] | null;
// following attributes are filled during searching in the database
@ -85,7 +86,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
/** number of note revisions for this note */
private revisionCount!: number | null;
constructor(row: NoteRow) {
constructor(row: Partial<NoteRow>) {
super();
if (!row) {
@ -96,7 +97,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
this.init();
}
updateFromRow(row: NoteRow) {
updateFromRow(row: Partial<NoteRow>) {
this.update([
row.noteId,
row.title,
@ -215,17 +216,15 @@ class BNote extends AbstractBeccaEntity<BNote> {
* - changes in the note metadata or title should not trigger note content sync (so we keep separate utcDateModified and entity changes records)
* - but to the user note content and title changes are one and the same - single dateModified (so all changes must go through Note and content is not a separate entity)
*/
/** @returns {string|Buffer} */
getContent() {
return this._getContent();
// FIXME: original declaration was (string | Buffer), but everywhere it's used as a string.
getContent(): string {
return this._getContent() as string;
}
/**
* @returns {*}
* @throws Error in case of invalid JSON */
getJsonContent() {
const content = this.getContent() as string;
getJsonContent(): {} | null {
const content = this.getContent();
if (!content || !content.trim()) {
return null;
@ -1496,7 +1495,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
return null;
}
const content = this.getContent() as string;
const content = this.getContent();
const parentNote = this.getParentNotes()[0];
const attachment = parentNote.saveAttachment({
@ -1506,7 +1505,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
content: content
});
let parentContent = parentNote.getContent() as string;
let parentContent = parentNote.getContent();
const oldNoteUrl = `api/images/${this.noteId}/`;
const newAttachmentUrl = `api/attachments/${attachment.attachmentId}/image/`;
@ -1584,7 +1583,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
*/
saveRevision() {
return sql.transactional(() => {
let noteContent = this.getContent() as string;
let noteContent = this.getContent();
const revision = new BRevision({
noteId: this.noteId,

View File

@ -7,7 +7,7 @@ import { OptionRow } from './rows';
/**
* Option represents a name-value pair, either directly configurable by the user or some system property.
*/
class BOption extends AbstractBeccaEntity {
class BOption extends AbstractBeccaEntity<BOption> {
static get entityName() { return "options"; }
static get primaryKeyName() { return "name"; }
static get hashedProperties() { return ["name", "value"]; }

View File

@ -7,10 +7,8 @@ import AbstractBeccaEntity = require('./abstract_becca_entity.js');
/**
* RecentNote represents recently visited note.
*
* @extends AbstractBeccaEntity
*/
class BRecentNote extends AbstractBeccaEntity {
class BRecentNote extends AbstractBeccaEntity<BRecentNote> {
static get entityName() { return "recent_notes"; }
static get primaryKeyName() { return "noteId"; }

View File

@ -28,18 +28,19 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
static get hashedProperties() { return ["revisionId", "noteId", "title", "isProtected", "dateLastEdited", "dateCreated",
"utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; }
revisionId: string;
revisionId?: string;
noteId: string;
type: string;
mime: string;
isProtected: boolean;
title: string;
blobId: string;
dateLastEdited: string;
blobId?: string;
dateLastEdited?: string;
dateCreated: string;
utcDateLastEdited: string;
utcDateLastEdited?: string;
utcDateCreated: string;
contentLength?: number;
content?: string;
constructor(row: RevisionRow, titleDecrypted = false) {
super();
@ -68,8 +69,8 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
return becca.notes[this.noteId];
}
/** @returns {boolean} true if the note has string content (not binary) */
hasStringContent() {
/** @returns true if the note has string content (not binary) */
hasStringContent(): boolean {
return utils.isStringNote(this.type, this.mime);
}
@ -87,8 +88,9 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
*
* This is the same approach as is used for Note's content.
*/
getContent(): string | Buffer {
return this._getContent();
// FIXME: initial declaration included Buffer, but everywhere it's treated as a string.
getContent(): string {
return this._getContent() as string;
}
/**

View File

@ -93,7 +93,7 @@ function getOptionMap() {
return map;
}
module.exports = {
export = {
getOption,
getOptionInt,
getOptionBool,