diff --git a/src/becca/entities/battribute.js b/src/becca/entities/battribute.js
index 61213061a..e57691e94 100644
--- a/src/becca/entities/battribute.js
+++ b/src/becca/entities/battribute.js
@@ -141,7 +141,7 @@ class BAttribute extends AbstractBeccaEntity {
*/
getTargetNote() {
if (this.type !== 'relation') {
- throw new Error(`Attribute ${this.attributeId} is not relation`);
+ throw new Error(`Attribute '${this.attributeId}' is not a relation.`);
}
if (!this.value) {
diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js
index ac56bceb2..c20db6f1c 100644
--- a/src/becca/entities/bnote.js
+++ b/src/becca/entities/bnote.js
@@ -1445,14 +1445,16 @@ class BNote extends AbstractBeccaEntity {
const targetRelations = this.getTargetRelations().filter(relation => relation.name === 'imageLink');
- if (targetRelations.length !== 1) {
+ if (targetRelations.length > 1) {
return false;
}
const parentNote = this.getParentNotes()[0]; // at this point note can have only one parent
- const referencingNote = targetRelations[0].getNote();
+ const referencingNote = targetRelations[0]?.getNote();
- if (parentNote !== referencingNote || parentNote.type !== 'text' || !parentNote.isContentAvailable()) {
+ if (referencingNote && parentNote !== referencingNote) {
+ return false;
+ } else if (parentNote.type !== 'text' || !parentNote.isContentAvailable()) {
return false;
}
diff --git a/src/becca/entity_constructor.js b/src/becca/entity_constructor.js
index bd4e125bf..d04702e6a 100644
--- a/src/becca/entity_constructor.js
+++ b/src/becca/entity_constructor.js
@@ -20,7 +20,7 @@ const ENTITY_NAME_TO_ENTITY = {
function getEntityFromEntityName(entityName) {
if (!(entityName in ENTITY_NAME_TO_ENTITY)) {
- throw new Error(`Entity for table ${entityName} not found!`);
+ throw new Error(`Entity for table '${entityName}' not found!`);
}
return ENTITY_NAME_TO_ENTITY[entityName];
diff --git a/src/etapi/auth.js b/src/etapi/auth.js
index 921c91d94..8190c1bd2 100644
--- a/src/etapi/auth.js
+++ b/src/etapi/auth.js
@@ -29,7 +29,7 @@ function register(router, loginMiddleware) {
if (!etapiToken) {
// shouldn't happen since this already passed auth validation
- throw new Error(`Cannot find the token ${parsed.etapiTokenId}.`);
+ throw new Error(`Cannot find the token '${parsed.etapiTokenId}'.`);
}
etapiToken.markAsDeletedSimple();
diff --git a/src/public/app/entities/fnote.js b/src/public/app/entities/fnote.js
index cfe53cd84..9f942cd95 100644
--- a/src/public/app/entities/fnote.js
+++ b/src/public/app/entities/fnote.js
@@ -252,14 +252,16 @@ class FNote {
const targetRelations = this.getTargetRelations().filter(relation => relation.name === 'imageLink');
- if (targetRelations.length !== 1) {
+ if (targetRelations.length > 1) {
return false;
}
const parentNote = this.getParentNotes()[0]; // at this point note can have only one parent
- const referencingNote = targetRelations[0].getNote();
+ const referencingNote = targetRelations[0]?.getNote();
- if (parentNote !== referencingNote || parentNote.type !== 'text' || !parentNote.isContentAvailable()) {
+ if (referencingNote && referencingNote !== parentNote) {
+ return false;
+ } else if (parentNote.type !== 'text' || !parentNote.isContentAvailable()) {
return false;
}
diff --git a/src/public/app/widgets/containers/flex_container.js b/src/public/app/widgets/containers/flex_container.js
index 7ece8aff0..ae3ffb107 100644
--- a/src/public/app/widgets/containers/flex_container.js
+++ b/src/public/app/widgets/containers/flex_container.js
@@ -5,7 +5,7 @@ export default class FlexContainer extends Container {
super();
if (!direction || !['row', 'column'].includes(direction)) {
- throw new Error(`Direction argument given as "${direction}", use either 'row' or 'column'`);
+ throw new Error(`Direction argument given as '${direction}', use either 'row' or 'column'`);
}
this.attrs.style = `display: flex; flex-direction: ${direction};`;
diff --git a/src/public/app/widgets/dialogs/export.js b/src/public/app/widgets/dialogs/export.js
index 9fcb098ba..9e23d11d0 100644
--- a/src/public/app/widgets/dialogs/export.js
+++ b/src/public/app/widgets/dialogs/export.js
@@ -203,7 +203,7 @@ export default class ExportDialog extends BasicWidget {
this.$singleType.prop("checked", true).trigger('change');
}
else {
- throw new Error(`Unrecognized type ${defaultType}`);
+ throw new Error(`Unrecognized type '${defaultType}'`);
}
this.$widget.find(".opml-v2").prop("checked", true); // setting default
diff --git a/src/public/app/widgets/mobile_widgets/mobile_detail_menu.js b/src/public/app/widgets/mobile_widgets/mobile_detail_menu.js
index 84430c7d1..56b237398 100644
--- a/src/public/app/widgets/mobile_widgets/mobile_detail_menu.js
+++ b/src/public/app/widgets/mobile_widgets/mobile_detail_menu.js
@@ -32,7 +32,7 @@ class MobileDetailMenuWidget extends BasicWidget {
const branchId = await treeService.getBranchIdFromNotePath(notePath);
if (!branchId) {
- throw new Error(`Cannot get branchId for notePath ${notePath}`);
+ throw new Error(`Cannot get branchId for notePath '${notePath}'`);
}
if (await branchService.deleteNotes([branchId])) {
diff --git a/src/public/app/widgets/note_detail.js b/src/public/app/widgets/note_detail.js
index 6b6302c85..0784224fc 100644
--- a/src/public/app/widgets/note_detail.js
+++ b/src/public/app/widgets/note_detail.js
@@ -174,7 +174,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
getTypeWidget() {
if (!this.typeWidgets[this.type]) {
- throw new Error(`Could not find typeWidget for type: ${this.type}`);
+ throw new Error(`Could not find typeWidget for type '${this.type}'`);
}
return this.typeWidgets[this.type];
diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js
index 1bf03d2ce..8221fd448 100644
--- a/src/public/app/widgets/note_tree.js
+++ b/src/public/app/widgets/note_tree.js
@@ -475,7 +475,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
} else if (data.hitMode === "over") {
branchService.moveToParentNote(selectedBranchIds, node.data.branchId);
} else {
- throw new Error(`Unknown hitMode=${data.hitMode}`);
+ throw new Error(`Unknown hitMode '${data.hitMode}'`);
}
}
}
@@ -691,7 +691,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
const note = branch.getNoteFromCache();
if (!note) {
- throw new Error(`Branch "${branch.branchId}" has no child note "${branch.noteId}"`);
+ throw new Error(`Branch '${branch.branchId}' has no child note '${branch.noteId}'`);
}
const title = `${branch.prefix ? (`${branch.prefix} - `) : ""}${note.title}`;
diff --git a/src/public/app/widgets/ribbon_widgets/book_properties.js b/src/public/app/widgets/ribbon_widgets/book_properties.js
index 7aff9a5aa..3bc1e51fc 100644
--- a/src/public/app/widgets/ribbon_widgets/book_properties.js
+++ b/src/public/app/widgets/ribbon_widgets/book_properties.js
@@ -101,7 +101,7 @@ export default class BookPropertiesWidget extends NoteContextAwareWidget {
async toggleViewType(type) {
if (type !== 'list' && type !== 'grid') {
- throw new Error(`Invalid view type ${type}`);
+ throw new Error(`Invalid view type '${type}'`);
}
await attributeService.setLabel(this.noteId, 'viewType', type);
diff --git a/src/public/app/widgets/type_widgets/attachment_list.js b/src/public/app/widgets/type_widgets/attachment_list.js
index 0072a14be..e4876e995 100644
--- a/src/public/app/widgets/type_widgets/attachment_list.js
+++ b/src/public/app/widgets/type_widgets/attachment_list.js
@@ -33,7 +33,7 @@ export default class AttachmentListTypeWidget extends TypeWidget {
const attachments = await server.get(`notes/${this.noteId}/attachments?includeContent=true`);
if (attachments.length === 0) {
- this.$list.html("This note has no attachments.");
+ this.$list.html('
This note has no attachments.
');
return;
}
diff --git a/src/public/app/widgets/type_widgets/image.js b/src/public/app/widgets/type_widgets/image.js
index d35f9b634..53c8e3ba1 100644
--- a/src/public/app/widgets/type_widgets/image.js
+++ b/src/public/app/widgets/type_widgets/image.js
@@ -79,7 +79,7 @@ class ImageTypeWidget extends TypeWidget {
utils.dynamicRequire('electron');
webContents.copyImageAt(e.pageX, e.pageY);
} else {
- throw new Error(`Unrecognized command ${command}`);
+ throw new Error(`Unrecognized command '${command}'`);
}
}
});
diff --git a/src/routes/api/branches.js b/src/routes/api/branches.js
index 5bc8a3c70..0c1f1f34e 100644
--- a/src/routes/api/branches.js
+++ b/src/routes/api/branches.js
@@ -24,7 +24,7 @@ function moveBranchToParent(req) {
const branchToMove = becca.getBranch(branchId);
if (!parentBranch || !branchToMove) {
- throw new ValidationError(`One or both branches ${branchId}, ${parentBranchId} have not been found`);
+ throw new ValidationError(`One or both branches '${branchId}', '${parentBranchId}' have not been found`);
}
return branchService.moveBranchToBranch(branchToMove, parentBranch, branchId);
diff --git a/src/routes/api/options.js b/src/routes/api/options.js
index 900ea49d4..89a02d726 100644
--- a/src/routes/api/options.js
+++ b/src/routes/api/options.js
@@ -93,7 +93,7 @@ function updateOptions(req) {
if (!update(optionName, req.body[optionName])) {
// this should be improved
// it should return 400 instead of current 500, but at least it now rollbacks transaction
- throw new Error(`${optionName} is not allowed to change`);
+ throw new Error(`Option '${optionName}' is not allowed to be changed`);
}
}
}
diff --git a/src/services/cloning.js b/src/services/cloning.js
index 30235fbc1..eaa7682da 100644
--- a/src/services/cloning.js
+++ b/src/services/cloning.js
@@ -48,7 +48,7 @@ function cloneNoteToBranch(noteId, parentBranchId, prefix) {
const parentBranch = becca.getBranch(parentBranchId);
if (!parentBranch) {
- return { success: false, message: `Parent branch ${parentBranchId} does not exist.` };
+ return { success: false, message: `Parent branch '${parentBranchId}' does not exist.` };
}
const ret = cloneNoteToParentNote(noteId, parentBranch.noteId, prefix);
diff --git a/src/services/date_utils.js b/src/services/date_utils.js
index 5c9a4a835..6c39ac1b1 100644
--- a/src/services/date_utils.js
+++ b/src/services/date_utils.js
@@ -47,7 +47,7 @@ function parseDateTime(str) {
return new Date(Date.parse(str));
}
catch (e) {
- throw new Error(`Can't parse date from ${str}: ${e.stack}`);
+ throw new Error(`Can't parse date from '${str}': ${e.stack}`);
}
}
diff --git a/src/services/entity_changes.js b/src/services/entity_changes.js
index 51fad2520..4b58fad46 100644
--- a/src/services/entity_changes.js
+++ b/src/services/entity_changes.js
@@ -137,7 +137,7 @@ function fillEntityChanges(entityName, entityPrimaryKey, condition = '') {
}
if (createdCount > 0) {
- log.info(`Created ${createdCount} missing entity changes for ${entityName}.`);
+ log.info(`Created ${createdCount} missing entity changes for entity '${entityName}'.`);
}
});
}
diff --git a/src/services/etapi_tokens.js b/src/services/etapi_tokens.js
index bdb65800b..23e71e4f0 100644
--- a/src/services/etapi_tokens.js
+++ b/src/services/etapi_tokens.js
@@ -97,7 +97,7 @@ function renameToken(etapiTokenId, newName) {
const etapiToken = becca.getEtapiToken(etapiTokenId);
if (!etapiToken) {
- throw new Error(`Token ${etapiTokenId} does not exist`);
+ throw new Error(`Token '${etapiTokenId}' does not exist`);
}
etapiToken.name = newName;
diff --git a/src/services/events.js b/src/services/events.js
index f188ffe71..91dda3e23 100644
--- a/src/services/events.js
+++ b/src/services/events.js
@@ -49,7 +49,7 @@ function emit(eventType, data) {
listener(data);
}
catch (e) {
- log.error(`Listener threw error: ${e.stack}`);
+ log.error(`Listener threw error: ${e.message}, stack: ${e.stack}`);
// we won't stop execution because of listener
}
}
diff --git a/src/services/handlers.js b/src/services/handlers.js
index b1ccfa63f..1cdaa2cb7 100644
--- a/src/services/handlers.js
+++ b/src/services/handlers.js
@@ -218,11 +218,8 @@ eventService.subscribe(eventService.ENTITY_DELETED, ({ entityName, entity }) =>
if (entityName === 'notes' && entity.noteId.startsWith("_")) {
// "named" note has been deleted, we will probably need to rebuild the hidden subtree
// scheduling so that bulk deletes won't trigger so many checks
- oneTimeTimer.scheduleExecution('hidden-subtree-check', 1000, () => {
- console.log("Checking hidden subtree");
-
- hiddenSubtreeService.checkHiddenSubtree();
- });
+ oneTimeTimer.scheduleExecution('hidden-subtree-check', 1000,
+ () => hiddenSubtreeService.checkHiddenSubtree());
}
});
diff --git a/src/services/hoisted_note.js b/src/services/hoisted_note.js
index ea12a17f5..de64f2da0 100644
--- a/src/services/hoisted_note.js
+++ b/src/services/hoisted_note.js
@@ -17,7 +17,7 @@ function isHoistedInHiddenSubtree() {
const hoistedNote = becca.getNote(hoistedNoteId);
if (!hoistedNote) {
- throw new Error(`Cannot find hoisted note ${hoistedNoteId}`);
+ throw new Error(`Cannot find hoisted note '${hoistedNoteId}'`);
}
return hoistedNote.isHiddenCompletely();
diff --git a/src/services/notes.js b/src/services/notes.js
index aea15551d..d0902161a 100644
--- a/src/services/notes.js
+++ b/src/services/notes.js
@@ -116,7 +116,7 @@ function getAndValidateParent(params) {
const parentNote = becca.notes[params.parentNoteId];
if (!parentNote) {
- throw new ValidationError(`Parent note "${params.parentNoteId}" not found.`);
+ throw new ValidationError(`Parent note '${params.parentNoteId}' was not found.`);
}
if (parentNote.type === 'launcher' && parentNote.noteId !== '_lbBookmarks') {
@@ -281,7 +281,7 @@ function createNewNoteWithTarget(target, targetBranchId, params) {
return retObject;
}
else {
- throw new Error(`Unknown target ${target}`);
+ throw new Error(`Unknown target '${target}'`);
}
}
@@ -883,11 +883,15 @@ function eraseUnusedBlobs() {
FROM blobs
LEFT JOIN notes ON notes.blobId = blobs.blobId
LEFT JOIN attachments ON attachments.blobId = blobs.blobId
- LEFT JOIN note_revisions ON attachments.blobId = blobs.blobId
+ LEFT JOIN note_revisions ON note_revisions.blobId = blobs.blobId
WHERE notes.noteId IS NULL
AND attachments.attachmentId IS NULL
AND note_revisions.noteRevisionId IS NULL`);
+ if (unusedBlobIds.length === 0) {
+ return;
+ }
+
sql.executeMany(`DELETE FROM blobs WHERE blobId IN (???)`, unusedBlobIds);
setEntityChangesAsErased(sql.getManyRows(`SELECT * FROM entity_changes WHERE entityName = 'blobs' AND entityId IN (???)`, unusedBlobIds));
diff --git a/src/services/options.js b/src/services/options.js
index 9d227ec4c..62d4c5aa2 100644
--- a/src/services/options.js
+++ b/src/services/options.js
@@ -10,7 +10,7 @@ function getOptionOrNull(name) {
// e.g. in initial sync becca is not loaded because DB is not initialized
option = sql.getRow("SELECT * FROM options WHERE name = ?", name);
}
-
+
return option ? option.value : null;
}
@@ -33,7 +33,7 @@ function getOptionInt(name) {
const intVal = parseInt(val);
if (isNaN(intVal)) {
- throw new Error(`Could not parse "${val}" into integer for option "${name}"`);
+ throw new Error(`Could not parse '${val}' into integer for option '${name}'`);
}
return intVal;
@@ -46,7 +46,7 @@ function getOptionBool(name) {
const val = getOption(name);
if (!['true', 'false'].includes(val)) {
- throw new Error(`Could not parse "${val}" into boolean for option "${name}"`);
+ throw new Error(`Could not parse '${val}' into boolean for option '${name}'`);
}
return val === 'true';
diff --git a/src/services/request.js b/src/services/request.js
index 78370ad7d..3b42670ad 100644
--- a/src/services/request.js
+++ b/src/services/request.js
@@ -182,7 +182,7 @@ function getClient(opts) {
return require(protocol.substr(0, protocol.length - 1));
}
else {
- throw new Error(`Unrecognized protocol "${protocol}"`);
+ throw new Error(`Unrecognized protocol '${protocol}'`);
}
}
}
diff --git a/src/services/sync.js b/src/services/sync.js
index 77622d6ce..d6b8d004a 100644
--- a/src/services/sync.js
+++ b/src/services/sync.js
@@ -109,7 +109,7 @@ async function doLogin() {
});
if (resp.instanceId === instanceId) {
- throw new Error(`Sync server has member ID ${resp.instanceId} which is also local. This usually happens when the sync client is (mis)configured to sync with itself (URL points back to client) instead of the correct sync server.`);
+ throw new Error(`Sync server has member ID '${resp.instanceId}' which is also local. This usually happens when the sync client is (mis)configured to sync with itself (URL points back to client) instead of the correct sync server.`);
}
syncContext.instanceId = resp.instanceId;
@@ -312,13 +312,13 @@ function getEntityChangeRow(entityName, entityId) {
const primaryKey = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName;
if (!primaryKey) {
- throw new Error(`Unknown entity ${entityName}`);
+ throw new Error(`Unknown entity '${entityName}'`);
}
const entity = sql.getRow(`SELECT * FROM ${entityName} WHERE ${primaryKey} = ?`, [entityId]);
if (!entity) {
- throw new Error(`Entity ${entityName} ${entityId} not found.`);
+ throw new Error(`Entity ${entityName} '${entityId}' not found.`);
}
if (entityName === 'blobs' && entity.content !== null) {
diff --git a/src/services/tree.js b/src/services/tree.js
index 5c3798680..5e77a9504 100644
--- a/src/services/tree.js
+++ b/src/services/tree.js
@@ -200,7 +200,7 @@ function setNoteToParent(noteId, prefix, parentNoteId) {
const parentNote = becca.getNote(parentNoteId);
if (parentNote && parentNote.isDeleted) {
- throw new Error(`Cannot move note to deleted parent note ${parentNoteId}`);
+ throw new Error(`Cannot move note to deleted parent note '${parentNoteId}'`);
}
// case where there might be more such branches is ignored. It's expected there should be just one
@@ -224,7 +224,7 @@ function setNoteToParent(noteId, prefix, parentNoteId) {
const note = becca.getNote(noteId);
if (note.isDeleted) {
- throw new Error(`Cannot create a branch for ${noteId} which is deleted.`);
+ throw new Error(`Cannot create a branch for '${noteId}' which is deleted.`);
}
const branchId = sql.getValue('SELECT branchId FROM branches WHERE isDeleted = 0 AND noteId = ? AND parentNoteId = ?', [noteId, parentNoteId]);
diff --git a/src/share/shaca/entities/sattribute.js b/src/share/shaca/entities/sattribute.js
index 9e0509aa9..dea4b950e 100644
--- a/src/share/shaca/entities/sattribute.js
+++ b/src/share/shaca/entities/sattribute.js
@@ -89,7 +89,7 @@ class SAttribute extends AbstractShacaEntity {
/** @returns {SNote|null} */
getTargetNote() {
if (this.type !== 'relation') {
- throw new Error(`Attribute ${this.attributeId} is not relation`);
+ throw new Error(`Attribute '${this.attributeId}' is not relation`);
}
if (!this.value) {