mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
Merge pull request #242 from TriliumNext/feature/server_esm_part2
Server ESM port: Convert some of the asynchronous imports
This commit is contained in:
commit
0606fe01f6
@ -1,6 +1,8 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import electron from "electron";
|
import electron from "electron";
|
||||||
|
import electronDebug from "electron-debug";
|
||||||
|
import electronDl from "electron-dl";
|
||||||
import sqlInit from "./src/services/sql_init.js";
|
import sqlInit from "./src/services/sql_init.js";
|
||||||
import appIconService from "./src/services/app_icon.js";
|
import appIconService from "./src/services/app_icon.js";
|
||||||
import windowService from "./src/services/window.js";
|
import windowService from "./src/services/window.js";
|
||||||
@ -12,11 +14,11 @@ if (require('electron-squirrel-startup')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adds debug features like hotkeys for triggering dev tools and reload
|
// Adds debug features like hotkeys for triggering dev tools and reload
|
||||||
require('electron-debug')();
|
electronDebug();
|
||||||
|
|
||||||
appIconService.installLocalAppIcon();
|
appIconService.installLocalAppIcon();
|
||||||
|
|
||||||
require('electron-dl')({ saveAs: true });
|
electronDl({ saveAs: true });
|
||||||
|
|
||||||
// needed for excalidraw export https://github.com/zadam/trilium/issues/4271
|
// needed for excalidraw export https://github.com/zadam/trilium/issues/4271
|
||||||
electron.app.commandLine.appendSwitch(
|
electron.app.commandLine.appendSwitch(
|
||||||
|
11
package-lock.json
generated
11
package-lock.json
generated
@ -111,6 +111,7 @@
|
|||||||
"@types/sax": "^1.2.7",
|
"@types/sax": "^1.2.7",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/semver": "^7.5.8",
|
||||||
"@types/serve-favicon": "^2.5.7",
|
"@types/serve-favicon": "^2.5.7",
|
||||||
|
"@types/session-file-store": "^1.2.5",
|
||||||
"@types/stream-throttle": "^0.1.4",
|
"@types/stream-throttle": "^0.1.4",
|
||||||
"@types/tmp": "^0.2.6",
|
"@types/tmp": "^0.2.6",
|
||||||
"@types/turndown": "^5.0.4",
|
"@types/turndown": "^5.0.4",
|
||||||
@ -2614,6 +2615,16 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/session-file-store": {
|
||||||
|
"version": "1.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/session-file-store/-/session-file-store-1.2.5.tgz",
|
||||||
|
"integrity": "sha512-xjIyh40IznXLrvbAY/nmxu5cMcPcE3ZoDrSDvd02m6p8UjUgOtZAGI7Os5DDd6THuxClLWNhFo/awy1tYp64Bg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*",
|
||||||
|
"@types/express-session": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/stream-throttle": {
|
"node_modules/@types/stream-throttle": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/stream-throttle/-/stream-throttle-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stream-throttle/-/stream-throttle-0.1.4.tgz",
|
||||||
|
@ -144,6 +144,7 @@
|
|||||||
"@types/sax": "^1.2.7",
|
"@types/sax": "^1.2.7",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/semver": "^7.5.8",
|
||||||
"@types/serve-favicon": "^2.5.7",
|
"@types/serve-favicon": "^2.5.7",
|
||||||
|
"@types/session-file-store": "^1.2.5",
|
||||||
"@types/stream-throttle": "^0.1.4",
|
"@types/stream-throttle": "^0.1.4",
|
||||||
"@types/tmp": "^0.2.6",
|
"@types/tmp": "^0.2.6",
|
||||||
"@types/turndown": "^5.0.4",
|
"@types/turndown": "^5.0.4",
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
const handleParens = require('../../src/services/search/services/handle_parens');
|
import handleParens from "../../src/services/search/services/handle_parens";
|
||||||
|
import { TokenStructure } from "../../src/services/search/services/types";
|
||||||
|
|
||||||
describe("Parens handler", () => {
|
describe("Parens handler", () => {
|
||||||
it("handles parens", () => {
|
it("handles parens", () => {
|
||||||
const input = ["(", "hello", ")", "and", "(", "(", "pick", "one", ")", "and", "another", ")"]
|
const input = ["(", "hello", ")", "and", "(", "(", "pick", "one", ")", "and", "another", ")"]
|
||||||
.map(token => ({token}));
|
.map(token => ({token}));
|
||||||
|
|
||||||
expect(handleParens(input))
|
const actual: TokenStructure = [
|
||||||
.toEqual([
|
[
|
||||||
|
{token: "hello"}
|
||||||
|
],
|
||||||
|
{token: "and"},
|
||||||
|
[
|
||||||
[
|
[
|
||||||
{token: "hello"}
|
{token: "pick"},
|
||||||
|
{token: "one"}
|
||||||
],
|
],
|
||||||
{token: "and"},
|
{token: "and"},
|
||||||
[
|
{token: "another"}
|
||||||
[
|
]
|
||||||
{token: "pick"},
|
];
|
||||||
{token: "one"}
|
|
||||||
],
|
expect(handleParens(input)).toEqual(actual);
|
||||||
{token: "and"},
|
|
||||||
{token: "another"}
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -155,9 +155,7 @@ export default class Becca {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRevision(revisionId: string): BRevision | null {
|
getRevision(revisionId: string): BRevision | null {
|
||||||
const row = sql.getRow("SELECT * FROM revisions WHERE revisionId = ?", [revisionId]);
|
const row = sql.getRow<RevisionRow | null>("SELECT * FROM revisions WHERE revisionId = ?", [revisionId]);
|
||||||
|
|
||||||
const BRevision = require('./entities/brevision'); // avoiding circular dependency problems
|
|
||||||
return row ? new BRevision(row) : null;
|
return row ? new BRevision(row) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,9 +177,7 @@ export default class Becca {
|
|||||||
WHERE attachmentId = ? AND isDeleted = 0`
|
WHERE attachmentId = ? AND isDeleted = 0`
|
||||||
: `SELECT * FROM attachments WHERE attachmentId = ? AND isDeleted = 0`;
|
: `SELECT * FROM attachments WHERE attachmentId = ? AND isDeleted = 0`;
|
||||||
|
|
||||||
const BAttachment = require('./entities/battachment'); // avoiding circular dependency problems
|
return sql.getRows<AttachmentRow>(query, [attachmentId])
|
||||||
|
|
||||||
return sql.getRows(query, [attachmentId])
|
|
||||||
.map(row => new BAttachment(row))[0];
|
.map(row => new BAttachment(row))[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +190,6 @@ export default class Becca {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAttachments(attachmentIds: string[]): BAttachment[] {
|
getAttachments(attachmentIds: string[]): BAttachment[] {
|
||||||
const BAttachment = require('./entities/battachment'); // avoiding circular dependency problems
|
|
||||||
return sql.getManyRows<AttachmentRow>("SELECT * FROM attachments WHERE attachmentId IN (???) AND isDeleted = 0", attachmentIds)
|
return sql.getManyRows<AttachmentRow>("SELECT * FROM attachments WHERE attachmentId IN (???) AND isDeleted = 0", attachmentIds)
|
||||||
.map(row => new BAttachment(row));
|
.map(row => new BAttachment(row));
|
||||||
}
|
}
|
||||||
@ -204,9 +199,7 @@ export default class Becca {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const row = sql.getRow("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [entity.blobId]);
|
const row = sql.getRow<BBlob | null>("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [entity.blobId]);
|
||||||
|
|
||||||
const BBlob = require('./entities/bblob'); // avoiding circular dependency problems
|
|
||||||
return row ? new BBlob(row) : null;
|
return row ? new BBlob(row) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,16 +241,12 @@ export default class Becca {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRecentNotesFromQuery(query: string, params: string[] = []): BRecentNote[] {
|
getRecentNotesFromQuery(query: string, params: string[] = []): BRecentNote[] {
|
||||||
const rows = sql.getRows(query, params);
|
const rows = sql.getRows<BRecentNote>(query, params);
|
||||||
|
|
||||||
const BRecentNote = require('./entities/brecent_note'); // avoiding circular dependency problems
|
|
||||||
return rows.map(row => new BRecentNote(row));
|
return rows.map(row => new BRecentNote(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
getRevisionsFromQuery(query: string, params: string[] = []): BRevision[] {
|
getRevisionsFromQuery(query: string, params: string[] = []): BRevision[] {
|
||||||
const rows = sql.getRows<RevisionRow>(query, params);
|
const rows = sql.getRows<RevisionRow>(query, params);
|
||||||
|
|
||||||
const BRevision = require('./entities/brevision'); // avoiding circular dependency problems
|
|
||||||
return rows.map(row => new BRevision(row));
|
return rows.map(row => new BRevision(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,13 +14,15 @@ import cls from "../services/cls.js";
|
|||||||
import entityConstructor from "../becca/entity_constructor.js";
|
import entityConstructor from "../becca/entity_constructor.js";
|
||||||
import { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from './entities/rows';
|
import { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from './entities/rows';
|
||||||
import AbstractBeccaEntity from "./entities/abstract_becca_entity.js";
|
import AbstractBeccaEntity from "./entities/abstract_becca_entity.js";
|
||||||
|
import options_init from "../services/options_init.js";
|
||||||
|
import ws from "../services/ws.js";
|
||||||
|
|
||||||
const beccaLoaded = new Promise<void>((res, rej) => {
|
const beccaLoaded = new Promise<void>((res, rej) => {
|
||||||
sqlInit.dbReady.then(() => {
|
sqlInit.dbReady.then(() => {
|
||||||
cls.init(() => {
|
cls.init(() => {
|
||||||
load();
|
load();
|
||||||
|
|
||||||
require('../services/options_init').initStartupOptions();
|
options_init.initStartupOptions();
|
||||||
|
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
@ -73,7 +75,7 @@ function load() {
|
|||||||
function reload(reason: string) {
|
function reload(reason: string) {
|
||||||
load();
|
load();
|
||||||
|
|
||||||
require('../services/ws').reloadFrontend(reason || "becca reloaded");
|
ws.reloadFrontend(reason || "becca reloaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
eventService.subscribeBeccaLoader([eventService.ENTITY_CHANGE_SYNCED], ({ entityName, entityRow }) => {
|
eventService.subscribeBeccaLoader([eventService.ENTITY_CHANGE_SYNCED], ({ entityName, entityRow }) => {
|
||||||
|
@ -9,6 +9,7 @@ import log from "../../services/log.js";
|
|||||||
import { AttachmentRow } from './rows';
|
import { AttachmentRow } from './rows';
|
||||||
import BNote from "./bnote.js";
|
import BNote from "./bnote.js";
|
||||||
import BBranch from "./bbranch.js";
|
import BBranch from "./bbranch.js";
|
||||||
|
import noteService from "../../services/notes.js";
|
||||||
|
|
||||||
const attachmentRoleToNoteTypeMapping = {
|
const attachmentRoleToNoteTypeMapping = {
|
||||||
'image': 'image',
|
'image': 'image',
|
||||||
@ -157,8 +158,6 @@ class BAttachment extends AbstractBeccaEntity<BAttachment> {
|
|||||||
throw new Error(`Cannot convert protected attachment outside of protected session`);
|
throw new Error(`Cannot convert protected attachment outside of protected session`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteService = require('../../services/notes');
|
|
||||||
|
|
||||||
const { note, branch } = noteService.createNewNote({
|
const { note, branch } = noteService.createNewNote({
|
||||||
parentNoteId: this.ownerId,
|
parentNoteId: this.ownerId,
|
||||||
title: this.title,
|
title: this.title,
|
||||||
|
@ -8,6 +8,7 @@ import TaskContext from "../../services/task_context.js";
|
|||||||
import cls from "../../services/cls.js";
|
import cls from "../../services/cls.js";
|
||||||
import log from "../../services/log.js";
|
import log from "../../services/log.js";
|
||||||
import { BranchRow } from './rows';
|
import { BranchRow } from './rows';
|
||||||
|
import handlers from "../../services/handlers.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple
|
* Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple
|
||||||
@ -157,7 +158,6 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
|
|||||||
|
|
||||||
if (parentBranches.length === 1 && parentBranches[0] === this) {
|
if (parentBranches.length === 1 && parentBranches[0] === this) {
|
||||||
// needs to be run before branches and attributes are deleted and thus attached relations disappear
|
// needs to be run before branches and attributes are deleted and thus attached relations disappear
|
||||||
const handlers = require('../../services/handlers');
|
|
||||||
handlers.runAttachedRelations(note, 'runOnNoteDeletion', note);
|
handlers.runAttachedRelations(note, 'runOnNoteDeletion', note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,14 @@ import TaskContext from "../../services/task_context.js";
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import eventService from "../../services/events.js";
|
import eventService from "../../services/events.js";
|
||||||
import { AttachmentRow, NoteRow, NoteType, RevisionRow } from './rows';
|
import { AttachmentRow, AttributeType, NoteRow, NoteType, RevisionRow } from './rows';
|
||||||
import BBranch from "./bbranch.js";
|
import BBranch from "./bbranch.js";
|
||||||
import BAttribute from "./battribute.js";
|
import BAttribute from "./battribute.js";
|
||||||
import { NotePojo } from '../becca-interface';
|
import { NotePojo } from '../becca-interface';
|
||||||
|
import searchService from "../../services/search/services/search.js";
|
||||||
|
import cloningService, { CloneResponse } from "../../services/cloning.js";
|
||||||
|
import noteService from "../../services/notes.js";
|
||||||
|
import handlers from "../../services/handlers.js";
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
|
|
||||||
const LABEL = 'label';
|
const LABEL = 'label';
|
||||||
@ -890,11 +894,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const searchService = require('../../services/search/services/search');
|
const result = searchService.searchFromNote(this);
|
||||||
const {searchResultNoteIds} = searchService.searchFromNote(this);
|
|
||||||
|
|
||||||
const becca = this.becca;
|
const becca = this.becca;
|
||||||
return (searchResultNoteIds as string[]) // TODO: remove cast once search is converted
|
return (result.searchResultNoteIds)
|
||||||
.map(resultNoteId => becca.notes[resultNoteId])
|
.map(resultNoteId => becca.notes[resultNoteId])
|
||||||
.filter(note => !!note);
|
.filter(note => !!note);
|
||||||
}
|
}
|
||||||
@ -1261,7 +1263,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
* @param name - attribute name
|
* @param name - attribute name
|
||||||
* @param value - attribute value (optional)
|
* @param value - attribute value (optional)
|
||||||
*/
|
*/
|
||||||
setAttribute(type: string, name: string, value?: string) {
|
setAttribute(type: AttributeType, name: string, value?: string) {
|
||||||
const attributes = this.getOwnedAttributes();
|
const attributes = this.getOwnedAttributes();
|
||||||
const attr = attributes.find(attr => attr.type === type && attr.name === name);
|
const attr = attributes.find(attr => attr.type === type && attr.name === name);
|
||||||
|
|
||||||
@ -1274,8 +1276,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const BAttribute = require('./battribute');
|
|
||||||
|
|
||||||
new BAttribute({
|
new BAttribute({
|
||||||
noteId: this.noteId,
|
noteId: this.noteId,
|
||||||
type: type,
|
type: type,
|
||||||
@ -1310,9 +1310,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
* @param name - name of the attribute, not including the leading ~/#
|
* @param name - name of the attribute, not including the leading ~/#
|
||||||
* @param value - value of the attribute - text for labels, target note ID for relations; optional.
|
* @param value - value of the attribute - text for labels, target note ID for relations; optional.
|
||||||
*/
|
*/
|
||||||
addAttribute(type: string, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute {
|
addAttribute(type: AttributeType, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute {
|
||||||
const BAttribute = require('./battribute');
|
|
||||||
|
|
||||||
return new BAttribute({
|
return new BAttribute({
|
||||||
noteId: this.noteId,
|
noteId: this.noteId,
|
||||||
type: type,
|
type: type,
|
||||||
@ -1351,7 +1349,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
* @param name - attribute name
|
* @param name - attribute name
|
||||||
* @param value - attribute value (optional)
|
* @param value - attribute value (optional)
|
||||||
*/
|
*/
|
||||||
toggleAttribute(type: string, enabled: boolean, name: string, value?: string) {
|
toggleAttribute(type: AttributeType, enabled: boolean, name: string, value?: string) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
this.setAttribute(type, name, value);
|
this.setAttribute(type, name, value);
|
||||||
}
|
}
|
||||||
@ -1423,8 +1421,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
searchNotesInSubtree(searchString: string) {
|
searchNotesInSubtree(searchString: string) {
|
||||||
const searchService = require('../../services/search/services/search');
|
|
||||||
|
|
||||||
return searchService.searchNotes(searchString) as BNote[];
|
return searchService.searchNotes(searchString) as BNote[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1432,12 +1428,16 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
return this.searchNotesInSubtree(searchString)[0];
|
return this.searchNotesInSubtree(searchString)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneTo(parentNoteId: string) {
|
cloneTo(parentNoteId: string): CloneResponse {
|
||||||
const cloningService = require('../../services/cloning');
|
|
||||||
|
|
||||||
const branch = this.becca.getNote(parentNoteId)?.getParentBranches()[0];
|
const branch = this.becca.getNote(parentNoteId)?.getParentBranches()[0];
|
||||||
|
if (!branch?.branchId) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Unable to find the branch ID to clone."
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return cloningService.cloneNoteToBranch(this.noteId, branch?.branchId);
|
return cloningService.cloneNoteToBranch(this.noteId, branch.branchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
isEligibleForConversionToAttachment(opts: ConvertOpts = { autoConversion: false }) {
|
isEligibleForConversionToAttachment(opts: ConvertOpts = { autoConversion: false }) {
|
||||||
@ -1508,7 +1508,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
|
|
||||||
parentNote.setContent(fixedContent);
|
parentNote.setContent(fixedContent);
|
||||||
|
|
||||||
const noteService = require('../../services/notes');
|
|
||||||
noteService.asyncPostProcessContent(parentNote, fixedContent); // to mark an unused attachment for deletion
|
noteService.asyncPostProcessContent(parentNote, fixedContent); // to mark an unused attachment for deletion
|
||||||
|
|
||||||
this.deleteNote();
|
this.deleteNote();
|
||||||
@ -1535,7 +1534,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// needs to be run before branches and attributes are deleted and thus attached relations disappear
|
// needs to be run before branches and attributes are deleted and thus attached relations disappear
|
||||||
const handlers = require('../../services/handlers');
|
|
||||||
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
|
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
|
||||||
taskContext.noteDeletionHandlerTriggered = true;
|
taskContext.noteDeletionHandlerTriggered = true;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import AbstractBeccaEntity from "./abstract_becca_entity.js";
|
|||||||
import sql from "../../services/sql.js";
|
import sql from "../../services/sql.js";
|
||||||
import BAttachment from "./battachment.js";
|
import BAttachment from "./battachment.js";
|
||||||
import { AttachmentRow, RevisionRow } from './rows';
|
import { AttachmentRow, RevisionRow } from './rows';
|
||||||
|
import eraseService from "../../services/erase.js";
|
||||||
|
|
||||||
interface ContentOpts {
|
interface ContentOpts {
|
||||||
/** will also save this BRevision entity */
|
/** will also save this BRevision entity */
|
||||||
@ -164,7 +165,9 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
|
|||||||
* Revisions are not soft-deletable, they are immediately hard-deleted (erased).
|
* Revisions are not soft-deletable, they are immediately hard-deleted (erased).
|
||||||
*/
|
*/
|
||||||
eraseRevision() {
|
eraseRevision() {
|
||||||
require('../../services/erase.js').eraseRevisions([this.revisionId]);
|
if (this.revisionId) {
|
||||||
|
eraseService.eraseRevisions([this.revisionId]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeSaving() {
|
beforeSaving() {
|
||||||
|
@ -42,7 +42,7 @@ export interface OptionRow {
|
|||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
isSynced: boolean;
|
isSynced: boolean;
|
||||||
utcDateModified: string;
|
utcDateModified?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EtapiTokenRow {
|
export interface EtapiTokenRow {
|
||||||
@ -69,7 +69,7 @@ export interface AttributeRow {
|
|||||||
noteId?: string;
|
noteId?: string;
|
||||||
type: AttributeType;
|
type: AttributeType;
|
||||||
name: string;
|
name: string;
|
||||||
position?: number;
|
position?: number | null;
|
||||||
value?: string;
|
value?: string;
|
||||||
isInheritable?: boolean;
|
isInheritable?: boolean;
|
||||||
utcDateModified?: string;
|
utcDateModified?: string;
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
import imageService from "../../services/image.js";
|
import imageService from "../../services/image.js";
|
||||||
import becca from "../../becca/becca.js";
|
import becca from "../../becca/becca.js";
|
||||||
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import BNote from "../../becca/entities/bnote.js";
|
import BNote from "../../becca/entities/bnote.js";
|
||||||
import BRevision from "../../becca/entities/brevision.js";
|
import BRevision from "../../becca/entities/brevision.js";
|
||||||
import { AppRequest } from '../route-interface';
|
import { AppRequest } from '../route-interface';
|
||||||
|
import { RESOURCE_DIR } from "../../services/resource_dir.js";
|
||||||
|
|
||||||
function returnImageFromNote(req: Request, res: Response) {
|
function returnImageFromNote(req: Request, res: Response) {
|
||||||
const image = becca.getNote(req.params.noteId);
|
const image = becca.getNote(req.params.noteId);
|
||||||
|
@ -4,19 +4,19 @@ import { Request } from "express";
|
|||||||
|
|
||||||
import becca from "../../becca/becca.js";
|
import becca from "../../becca/becca.js";
|
||||||
import SearchContext from "../../services/search/search_context.js";
|
import SearchContext from "../../services/search/search_context.js";
|
||||||
import searchService from "../../services/search/services/search.js";
|
import searchService, { EMPTY_RESULT, SearchNoteResult } from "../../services/search/services/search.js";
|
||||||
import bulkActionService from "../../services/bulk_actions.js";
|
import bulkActionService from "../../services/bulk_actions.js";
|
||||||
import cls from "../../services/cls.js";
|
import cls from "../../services/cls.js";
|
||||||
import attributeFormatter from "../../services/attribute_formatter.js";
|
import attributeFormatter from "../../services/attribute_formatter.js";
|
||||||
import ValidationError from "../../errors/validation_error.js";
|
import ValidationError from "../../errors/validation_error.js";
|
||||||
import SearchResult from "../../services/search/search_result.js";
|
import SearchResult from "../../services/search/search_result.js";
|
||||||
|
|
||||||
function searchFromNote(req: Request) {
|
function searchFromNote(req: Request): SearchNoteResult {
|
||||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||||
|
|
||||||
if (!note) {
|
if (!note) {
|
||||||
// this can be triggered from recent changes, and it's harmless to return an empty list rather than fail
|
// this can be triggered from recent changes, and it's harmless to return an empty list rather than fail
|
||||||
return [];
|
return EMPTY_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.type !== 'search') {
|
if (note.type !== 'search') {
|
||||||
|
@ -14,6 +14,7 @@ import ws from "../../services/ws.js";
|
|||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { EntityChange, EntityChangeRecord } from '../../services/entity_changes_interface';
|
import { EntityChange, EntityChangeRecord } from '../../services/entity_changes_interface';
|
||||||
import ValidationError from "../../errors/validation_error.js";
|
import ValidationError from "../../errors/validation_error.js";
|
||||||
|
import consistencyChecksService from "../../services/consistency_checks.js";
|
||||||
|
|
||||||
async function testSync() {
|
async function testSync() {
|
||||||
try {
|
try {
|
||||||
@ -206,7 +207,7 @@ function queueSector(req: Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkEntityChanges() {
|
function checkEntityChanges() {
|
||||||
require('../../services/consistency_checks').runEntityChangesChecks();
|
consistencyChecksService.runEntityChangesChecks();
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import session from "express-session";
|
import session from "express-session";
|
||||||
|
import sessionFileStore from "session-file-store";
|
||||||
import sessionSecret from "../services/session_secret.js";
|
import sessionSecret from "../services/session_secret.js";
|
||||||
import dataDir from "../services/data_dir.js";
|
import dataDir from "../services/data_dir.js";
|
||||||
const FileStore = require('session-file-store')(session);
|
const FileStore = sessionFileStore(session);
|
||||||
|
|
||||||
const sessionParser = session({
|
const sessionParser = session({
|
||||||
secret: sessionSecret,
|
secret: sessionSecret,
|
||||||
|
@ -111,7 +111,7 @@ const ACTION_HANDLERS: Record<string, ActionHandler> = {
|
|||||||
res = branchService.moveBranchToNote(note.getParentBranches()[0], action.targetParentNoteId);
|
res = branchService.moveBranchToNote(note.getParentBranches()[0], action.targetParentNoteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res.success) {
|
if ("success" in res && !res.success) {
|
||||||
log.info(`Moving/cloning note ${note.noteId} to ${action.targetParentNoteId} failed with error ${JSON.stringify(res)}`);
|
log.info(`Moving/cloning note ${note.noteId} to ${action.targetParentNoteId} failed with error ${JSON.stringify(res)}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const sql = require('./sql');
|
import sql from './sql';
|
||||||
const eventChangesService = require('./entity_changes');
|
import eventChangesService from './entity_changes';
|
||||||
const treeService = require('./tree');
|
import treeService from './tree';
|
||||||
const BBranch = require('../becca/entities/bbranch');
|
import BBranch from '../becca/entities/bbranch';
|
||||||
const becca = require('../becca/becca');
|
import becca from '../becca/becca';
|
||||||
const log = require('./log');
|
import log from './log';
|
||||||
|
|
||||||
function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: string | null = null) {
|
export interface CloneResponse {
|
||||||
|
success: boolean;
|
||||||
|
message?: string;
|
||||||
|
branchId?: string;
|
||||||
|
notePath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: string | null = null): CloneResponse {
|
||||||
if (!(noteId in becca.notes) || !(parentNoteId in becca.notes)) {
|
if (!(noteId in becca.notes) || !(parentNoteId in becca.notes)) {
|
||||||
return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' };
|
return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentNote = becca.getNote(parentNoteId);
|
const parentNote = becca.getNote(parentNoteId);
|
||||||
|
if (!parentNote) {
|
||||||
|
return { success: false, message: 'Note cannot be cloned because the parent note could not be found.' };
|
||||||
|
}
|
||||||
|
|
||||||
if (parentNote.type === 'search') {
|
if (parentNote.type === 'search') {
|
||||||
return {
|
return {
|
||||||
@ -31,7 +41,7 @@ function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: str
|
|||||||
noteId: noteId,
|
noteId: noteId,
|
||||||
parentNoteId: parentNoteId,
|
parentNoteId: parentNoteId,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
isExpanded: 0
|
isExpanded: false
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
log.info(`Cloned note '${noteId}' to a new parent note '${parentNoteId}' with prefix '${prefix}'`);
|
log.info(`Cloned note '${noteId}' to a new parent note '${parentNoteId}' with prefix '${prefix}'`);
|
||||||
@ -43,7 +53,7 @@ function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: str
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function cloneNoteToBranch(noteId: string, parentBranchId: string, prefix: string) {
|
function cloneNoteToBranch(noteId: string, parentBranchId: string, prefix?: string) {
|
||||||
const parentBranch = becca.getBranch(parentBranchId);
|
const parentBranch = becca.getBranch(parentBranchId);
|
||||||
|
|
||||||
if (!parentBranch) {
|
if (!parentBranch) {
|
||||||
@ -67,6 +77,9 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi
|
|||||||
|
|
||||||
const parentNote = becca.getNote(parentNoteId);
|
const parentNote = becca.getNote(parentNoteId);
|
||||||
|
|
||||||
|
if (!parentNote) {
|
||||||
|
return { branch: null, success: false, message: "Can't find parent note." };
|
||||||
|
}
|
||||||
if (parentNote.type === 'search') {
|
if (parentNote.type === 'search') {
|
||||||
return { branch: null, success: false, message: "Can't clone into a search note" };
|
return { branch: null, success: false, message: "Can't clone into a search note" };
|
||||||
}
|
}
|
||||||
@ -81,7 +94,7 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi
|
|||||||
noteId: noteId,
|
noteId: noteId,
|
||||||
parentNoteId: parentNoteId,
|
parentNoteId: parentNoteId,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
isExpanded: 0
|
isExpanded: false
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
log.info(`Ensured note '${noteId}' is in parent note '${parentNoteId}' with prefix '${branch.prefix}'`);
|
log.info(`Ensured note '${noteId}' is in parent note '${parentNoteId}' with prefix '${branch.prefix}'`);
|
||||||
@ -90,7 +103,7 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ensureNoteIsAbsentFromParent(noteId: string, parentNoteId: string) {
|
function ensureNoteIsAbsentFromParent(noteId: string, parentNoteId: string) {
|
||||||
const branchId = sql.getValue(`SELECT branchId FROM branches WHERE noteId = ? AND parentNoteId = ? AND isDeleted = 0`, [noteId, parentNoteId]);
|
const branchId = sql.getValue<string>(`SELECT branchId FROM branches WHERE noteId = ? AND parentNoteId = ? AND isDeleted = 0`, [noteId, parentNoteId]);
|
||||||
const branch = becca.getBranch(branchId);
|
const branch = becca.getBranch(branchId);
|
||||||
|
|
||||||
if (branch) {
|
if (branch) {
|
||||||
@ -137,13 +150,13 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) {
|
|||||||
|
|
||||||
if (!(noteId in becca.notes)) {
|
if (!(noteId in becca.notes)) {
|
||||||
return { success: false, message: `Note to be cloned '${noteId}' is deleted or does not exist.` };
|
return { success: false, message: `Note to be cloned '${noteId}' is deleted or does not exist.` };
|
||||||
} else if (!(afterNote.parentNoteId in becca.notes)) {
|
} else if (!afterNote || !(afterNote.parentNoteId in becca.notes)) {
|
||||||
return { success: false, message: `After note '${afterNote.parentNoteId}' is deleted or does not exist.` };
|
return { success: false, message: `After note '${afterNote?.parentNoteId}' is deleted or does not exist.` };
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentNote = becca.getNote(afterNote.parentNoteId);
|
const parentNote = becca.getNote(afterNote.parentNoteId);
|
||||||
|
|
||||||
if (parentNote.type === 'search') {
|
if (!parentNote || parentNote.type === 'search') {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Can't clone into a search note"
|
message: "Can't clone into a search note"
|
||||||
@ -167,7 +180,7 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) {
|
|||||||
noteId: noteId,
|
noteId: noteId,
|
||||||
parentNoteId: afterNote.parentNoteId,
|
parentNoteId: afterNote.parentNoteId,
|
||||||
notePosition: afterNote.notePosition + 10,
|
notePosition: afterNote.notePosition + 10,
|
||||||
isExpanded: 0
|
isExpanded: false
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
log.info(`Cloned note '${noteId}' into parent note '${afterNote.parentNoteId}' after note '${afterNote.noteId}', branch '${afterBranchId}'`);
|
log.info(`Cloned note '${noteId}' into parent note '${afterNote.parentNoteId}' after note '${afterNote.noteId}', branch '${afterBranchId}'`);
|
||||||
|
@ -8,6 +8,7 @@ import becca from "../becca/becca.js";
|
|||||||
import blobService from "../services/blob.js";
|
import blobService from "../services/blob.js";
|
||||||
import { EntityChange } from './entity_changes_interface';
|
import { EntityChange } from './entity_changes_interface';
|
||||||
import type { Blob } from "./blob-interface";
|
import type { Blob } from "./blob-interface";
|
||||||
|
import eventService from "./events.js";
|
||||||
|
|
||||||
let maxEntityChangeId = 0;
|
let maxEntityChangeId = 0;
|
||||||
|
|
||||||
@ -57,8 +58,6 @@ function putNoteReorderingEntityChange(parentNoteId: string, componentId?: strin
|
|||||||
instanceId
|
instanceId
|
||||||
});
|
});
|
||||||
|
|
||||||
const eventService = require('./events');
|
|
||||||
|
|
||||||
eventService.emit(eventService.ENTITY_CHANGED, {
|
eventService.emit(eventService.ENTITY_CHANGED, {
|
||||||
entityName: 'note_reordering',
|
entityName: 'note_reordering',
|
||||||
entity: sql.getMap(`SELECT branchId, notePosition FROM branches WHERE isDeleted = 0 AND parentNoteId = ?`, [parentNoteId])
|
entity: sql.getMap(`SELECT branchId, notePosition FROM branches WHERE isDeleted = 0 AND parentNoteId = ?`, [parentNoteId])
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const log = require('./log');
|
import log from "./log";
|
||||||
|
|
||||||
const NOTE_TITLE_CHANGED = "NOTE_TITLE_CHANGED";
|
const NOTE_TITLE_CHANGED = "NOTE_TITLE_CHANGED";
|
||||||
const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION";
|
const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION";
|
||||||
|
@ -11,7 +11,6 @@ import protectedSessionService from "../protected_session.js";
|
|||||||
import sanitize from "sanitize-filename";
|
import sanitize from "sanitize-filename";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import becca from "../../becca/becca.js";
|
import becca from "../../becca/becca.js";
|
||||||
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
|
|
||||||
import archiver from "archiver";
|
import archiver from "archiver";
|
||||||
import log from "../log.js";
|
import log from "../log.js";
|
||||||
import TaskContext from "../task_context.js";
|
import TaskContext from "../task_context.js";
|
||||||
@ -21,6 +20,7 @@ import AttachmentMeta from "../meta/attachment_meta.js";
|
|||||||
import AttributeMeta from "../meta/attribute_meta.js";
|
import AttributeMeta from "../meta/attribute_meta.js";
|
||||||
import BBranch from "../../becca/entities/bbranch.js";
|
import BBranch from "../../becca/entities/bbranch.js";
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
|
import { RESOURCE_DIR } from "../resource_dir.js";
|
||||||
|
|
||||||
async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "html" | "markdown", res: Response | fs.WriteStream, setHeaders = true) {
|
async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "html" | "markdown", res: Response | fs.WriteStream, setHeaders = true) {
|
||||||
if (!['html', 'markdown'].includes(format)) {
|
if (!['html', 'markdown'].includes(format)) {
|
||||||
|
@ -156,7 +156,6 @@ function saveImageToAttachment(noteId: string, uploadBuffer: Buffer, originalNam
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
sql.transactional(() => {
|
sql.transactional(() => {
|
||||||
const note = becca.getNoteOrThrow(noteId);
|
const note = becca.getNoteOrThrow(noteId);
|
||||||
const noteService = require('../services/notes');
|
|
||||||
noteService.asyncPostProcessContent(note, note.getContent()); // to mark an unused attachment for deletion
|
noteService.asyncPostProcessContent(note, note.getContent()); // to mark an unused attachment for deletion
|
||||||
});
|
});
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
@ -12,6 +12,7 @@ import sanitizeAttributeName from "../sanitize_attribute_name.js";
|
|||||||
import TaskContext from "../task_context.js";
|
import TaskContext from "../task_context.js";
|
||||||
import BNote from "../../becca/entities/bnote.js";
|
import BNote from "../../becca/entities/bnote.js";
|
||||||
import { File } from "./common";
|
import { File } from "./common";
|
||||||
|
import { AttributeType } from "../../becca/entities/rows.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* date format is e.g. 20181121T193703Z or 2013-04-14T16:19:00.000Z (Mac evernote, see #3496)
|
* date format is e.g. 20181121T193703Z or 2013-04-14T16:19:00.000Z (Mac evernote, see #3496)
|
||||||
@ -29,7 +30,7 @@ function parseDate(text: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Attribute {
|
interface Attribute {
|
||||||
type: string;
|
type: AttributeType;
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ function checkDate(millisSinceMidnight: number) {
|
|||||||
return millisSinceMidnight;
|
return millisSinceMidnight;
|
||||||
}
|
}
|
||||||
|
|
||||||
function log(str: string) {
|
function log(str: string | Error) {
|
||||||
const bundleNoteId = cls.get("bundleNoteId");
|
const bundleNoteId = cls.get("bundleNoteId");
|
||||||
|
|
||||||
if (bundleNoteId) {
|
if (bundleNoteId) {
|
||||||
@ -66,11 +66,11 @@ function log(str: string) {
|
|||||||
console.log(str);
|
console.log(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
function info(message: string) {
|
function info(message: string | Error) {
|
||||||
log(message);
|
log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function error(message: string) {
|
function error(message: string | Error) {
|
||||||
log(`ERROR: ${message}`);
|
log(`ERROR: ${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import html2plaintext from "html2plaintext";
|
|||||||
import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType } from '../becca/entities/rows';
|
import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType } from '../becca/entities/rows';
|
||||||
import TaskContext from "./task_context.js";
|
import TaskContext from "./task_context.js";
|
||||||
import { NoteParams } from './note-interface';
|
import { NoteParams } from './note-interface';
|
||||||
|
import imageService from "./image.js";
|
||||||
|
|
||||||
interface FoundLink {
|
interface FoundLink {
|
||||||
name: "imageLink" | "internalLink" | "includeNoteLink" | "relationMapLink",
|
name: "imageLink" | "internalLink" | "includeNoteLink" | "relationMapLink",
|
||||||
@ -466,7 +467,7 @@ async function downloadImage(noteId: string, imageUrl: string) {
|
|||||||
const unescapedUrl = utils.unescapeHtml(imageUrl);
|
const unescapedUrl = utils.unescapeHtml(imageUrl);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let imageBuffer;
|
let imageBuffer: Buffer;
|
||||||
|
|
||||||
if (imageUrl.toLowerCase().startsWith("file://")) {
|
if (imageUrl.toLowerCase().startsWith("file://")) {
|
||||||
imageBuffer = await new Promise((res, rej) => {
|
imageBuffer = await new Promise((res, rej) => {
|
||||||
@ -487,10 +488,13 @@ async function downloadImage(noteId: string, imageUrl: string) {
|
|||||||
const parsedUrl = url.parse(unescapedUrl);
|
const parsedUrl = url.parse(unescapedUrl);
|
||||||
const title = path.basename(parsedUrl.pathname || "");
|
const title = path.basename(parsedUrl.pathname || "");
|
||||||
|
|
||||||
const imageService = require('../services/image');
|
|
||||||
const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, title, true, true);
|
const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, title, true, true);
|
||||||
|
|
||||||
imageUrlToAttachmentIdMapping[imageUrl] = attachment.attachmentId;
|
if (attachment.attachmentId) {
|
||||||
|
imageUrlToAttachmentIdMapping[imageUrl] = attachment.attachmentId;
|
||||||
|
} else {
|
||||||
|
log.error(`Download of '${imageUrl}' due to no attachment ID.`);
|
||||||
|
}
|
||||||
|
|
||||||
log.info(`Download of '${imageUrl}' succeeded and was saved as image attachment '${attachment.attachmentId}' of note '${noteId}'`);
|
log.info(`Download of '${imageUrl}' succeeded and was saved as image attachment '${attachment.attachmentId}' of note '${noteId}'`);
|
||||||
}
|
}
|
||||||
@ -520,7 +524,6 @@ function downloadImages(noteId: string, content: string) {
|
|||||||
const imageBase64 = url.substr(inlineImageMatch[0].length);
|
const imageBase64 = url.substr(inlineImageMatch[0].length);
|
||||||
const imageBuffer = Buffer.from(imageBase64, 'base64');
|
const imageBuffer = Buffer.from(imageBase64, 'base64');
|
||||||
|
|
||||||
const imageService = require('../services/image');
|
|
||||||
const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true);
|
const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true);
|
||||||
|
|
||||||
const encodedTitle = encodeURIComponent(attachment.title);
|
const encodedTitle = encodeURIComponent(attachment.title);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import becca from "../becca/becca.js";
|
import becca from "../becca/becca.js";
|
||||||
|
import BOption from "../becca/entities/boption.js";
|
||||||
import { OptionRow } from '../becca/entities/rows';
|
import { OptionRow } from '../becca/entities/rows';
|
||||||
import sql from "./sql.js";
|
import sql from "./sql.js";
|
||||||
|
|
||||||
@ -68,10 +69,7 @@ function setOption(name: string, value: string | number | boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOption(name: string, value: string | number, isSynced: boolean) {
|
function createOption(name: string, value: string, isSynced: boolean) {
|
||||||
// to avoid circular dependency, need to find a better solution
|
|
||||||
const BOption = require('../becca/entities/boption');
|
|
||||||
|
|
||||||
new BOption({
|
new BOption({
|
||||||
name: name,
|
name: name,
|
||||||
value: value,
|
value: value,
|
||||||
|
@ -137,7 +137,7 @@ function exec<T>(opts: ExecOpts): Promise<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImage(imageUrl: string) {
|
function getImage(imageUrl: string): Promise<Buffer> {
|
||||||
const proxyConf = syncOptions.getSyncProxy();
|
const proxyConf = syncOptions.getSyncProxy();
|
||||||
const opts: ClientOpts = {
|
const opts: ClientOpts = {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -149,7 +149,7 @@ function getImage(imageUrl: string) {
|
|||||||
const proxyAgent = getProxyAgent(opts);
|
const proxyAgent = getProxyAgent(opts);
|
||||||
const parsedTargetUrl = url.parse(opts.url);
|
const parsedTargetUrl = url.parse(opts.url);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<Buffer>((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const request = client.request({
|
const request = client.request({
|
||||||
method: opts.method,
|
method: opts.method,
|
||||||
@ -181,8 +181,7 @@ function getImage(imageUrl: string) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
request.end(undefined);
|
request.end(undefined);
|
||||||
}
|
} catch (e: any) {
|
||||||
catch (e: any) {
|
|
||||||
reject(generateError(opts, e.message));
|
reject(generateError(opts, e.message));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@ import log from "./log.js";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
const RESOURCE_DIR = path.resolve(__dirname, "../..");
|
export const RESOURCE_DIR = path.resolve(__dirname, "../..");
|
||||||
|
|
||||||
// where the "trilium" executable is
|
// where the "trilium" executable is
|
||||||
const ELECTRON_APP_ROOT_DIR = path.resolve(RESOURCE_DIR, "../..");
|
const ELECTRON_APP_ROOT_DIR = path.resolve(RESOURCE_DIR, "../..");
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { TokenData } from "./types";
|
import { TokenData, TokenStructure } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will create a recursive object from a list of tokens - tokens between parenthesis are grouped in a single array
|
* This will create a recursive object from a list of tokens - tokens between parenthesis are grouped in a single array
|
||||||
*/
|
*/
|
||||||
function handleParens(tokens: (TokenData | TokenData[])[]) {
|
function handleParens(tokens: TokenStructure) {
|
||||||
if (tokens.length === 0) {
|
if (tokens.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import utils from "../../utils.js";
|
|||||||
import TrueExp from "../expressions/true.js";
|
import TrueExp from "../expressions/true.js";
|
||||||
import IsHiddenExp from "../expressions/is_hidden.js";
|
import IsHiddenExp from "../expressions/is_hidden.js";
|
||||||
import SearchContext from "../search_context.js";
|
import SearchContext from "../search_context.js";
|
||||||
import { TokenData } from "./types";
|
import { TokenData, TokenStructure } from "./types";
|
||||||
import Expression from "../expressions/expression.js";
|
import Expression from "../expressions/expression.js";
|
||||||
|
|
||||||
function getFulltext(_tokens: TokenData[], searchContext: SearchContext) {
|
function getFulltext(_tokens: TokenData[], searchContext: SearchContext) {
|
||||||
@ -448,7 +448,7 @@ function getExpression(tokens: TokenData[], searchContext: SearchContext, level
|
|||||||
|
|
||||||
function parse({fulltextTokens, expressionTokens, searchContext}: {
|
function parse({fulltextTokens, expressionTokens, searchContext}: {
|
||||||
fulltextTokens: TokenData[],
|
fulltextTokens: TokenData[],
|
||||||
expressionTokens: (TokenData | TokenData[])[],
|
expressionTokens: TokenStructure,
|
||||||
searchContext: SearchContext,
|
searchContext: SearchContext,
|
||||||
originalQuery: string
|
originalQuery: string
|
||||||
}) {
|
}) {
|
||||||
|
@ -13,11 +13,24 @@ import log from "../../log.js";
|
|||||||
import hoistedNoteService from "../../hoisted_note.js";
|
import hoistedNoteService from "../../hoisted_note.js";
|
||||||
import BNote from "../../../becca/entities/bnote.js";
|
import BNote from "../../../becca/entities/bnote.js";
|
||||||
import BAttribute from "../../../becca/entities/battribute.js";
|
import BAttribute from "../../../becca/entities/battribute.js";
|
||||||
import { SearchParams, TokenData } from "./types";
|
import { SearchParams, TokenStructure } from "./types";
|
||||||
import Expression from "../expressions/expression.js";
|
import Expression from "../expressions/expression.js";
|
||||||
import sql from "../../sql.js";
|
import sql from "../../sql.js";
|
||||||
|
import scriptService from "../../script.js";
|
||||||
|
|
||||||
function searchFromNote(note: BNote) {
|
export interface SearchNoteResult {
|
||||||
|
searchResultNoteIds: string[];
|
||||||
|
highlightedTokens: string[];
|
||||||
|
error: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EMPTY_RESULT: SearchNoteResult = {
|
||||||
|
searchResultNoteIds: [],
|
||||||
|
highlightedTokens: [],
|
||||||
|
error: null
|
||||||
|
};
|
||||||
|
|
||||||
|
function searchFromNote(note: BNote): SearchNoteResult {
|
||||||
let searchResultNoteIds;
|
let searchResultNoteIds;
|
||||||
let highlightedTokens: string[];
|
let highlightedTokens: string[];
|
||||||
|
|
||||||
@ -78,7 +91,6 @@ function searchFromRelation(note: BNote, relationName: string) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const scriptService = require('../../script'); // TODO: to avoid circular dependency
|
|
||||||
const result = scriptService.executeNote(scriptNote, {originEntity: note});
|
const result = scriptService.executeNote(scriptNote, {originEntity: note});
|
||||||
|
|
||||||
if (!Array.isArray(result)) {
|
if (!Array.isArray(result)) {
|
||||||
@ -273,7 +285,7 @@ function parseQueryToExpression(query: string, searchContext: SearchContext) {
|
|||||||
const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query);
|
const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query);
|
||||||
searchContext.fulltextQuery = fulltextQuery;
|
searchContext.fulltextQuery = fulltextQuery;
|
||||||
|
|
||||||
let structuredExpressionTokens: (TokenData | TokenData[])[];
|
let structuredExpressionTokens: TokenStructure;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
structuredExpressionTokens = handleParens(expressionTokens);
|
structuredExpressionTokens = handleParens(expressionTokens);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
export type TokenStructure = (TokenData | TokenStructure)[];
|
||||||
|
|
||||||
export interface TokenData {
|
export interface TokenData {
|
||||||
token: string;
|
token: string;
|
||||||
inQuotes?: boolean;
|
inQuotes?: boolean;
|
||||||
|
@ -10,6 +10,9 @@ import dataDir from "./data_dir.js";
|
|||||||
import cls from "./cls.js";
|
import cls from "./cls.js";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import Database from "better-sqlite3";
|
import Database from "better-sqlite3";
|
||||||
|
import ws from "./ws.js";
|
||||||
|
import becca_loader from "../becca/becca_loader.js";
|
||||||
|
import entity_changes from "./entity_changes.js";
|
||||||
|
|
||||||
const dbConnection: DatabaseType = new Database(dataDir.DOCUMENT_PATH);
|
const dbConnection: DatabaseType = new Database(dataDir.DOCUMENT_PATH);
|
||||||
dbConnection.pragma('journal_mode = WAL');
|
dbConnection.pragma('journal_mode = WAL');
|
||||||
@ -248,7 +251,7 @@ function transactional<T>(func: (statement: Statement) => T) {
|
|||||||
const ret = (dbConnection.transaction(func) as any).deferred();
|
const ret = (dbConnection.transaction(func) as any).deferred();
|
||||||
|
|
||||||
if (!dbConnection.inTransaction) { // i.e. transaction was really committed (and not just savepoint released)
|
if (!dbConnection.inTransaction) { // i.e. transaction was really committed (and not just savepoint released)
|
||||||
require('./ws').sendTransactionEntityChangesToAllClients();
|
ws.sendTransactionEntityChangesToAllClients();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -259,11 +262,11 @@ function transactional<T>(func: (statement: Statement) => T) {
|
|||||||
if (entityChangeIds.length > 0) {
|
if (entityChangeIds.length > 0) {
|
||||||
log.info("Transaction rollback dirtied the becca, forcing reload.");
|
log.info("Transaction rollback dirtied the becca, forcing reload.");
|
||||||
|
|
||||||
require('../becca/becca_loader').load();
|
becca_loader.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
// the maxEntityChangeId has been incremented during failed transaction, need to recalculate
|
// the maxEntityChangeId has been incremented during failed transaction, need to recalculate
|
||||||
require('./entity_changes').recalculateMaxEntityChangeId();
|
entity_changes.recalculateMaxEntityChangeId();
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,10 @@ import migrationService from "./migration.js";
|
|||||||
import cls from "./cls.js";
|
import cls from "./cls.js";
|
||||||
import config from "./config.js";
|
import config from "./config.js";
|
||||||
import { OptionRow } from '../becca/entities/rows';
|
import { OptionRow } from '../becca/entities/rows';
|
||||||
|
import optionsInitService from "./options_init.js";
|
||||||
|
import BNote from "../becca/entities/bnote.js";
|
||||||
|
import BBranch from "../becca/entities/bbranch.js";
|
||||||
|
import zipImportService from "./import/zip.js";
|
||||||
|
|
||||||
const dbReady = utils.deferred<void>();
|
const dbReady = utils.deferred<void>();
|
||||||
|
|
||||||
@ -54,7 +58,7 @@ async function createInitialDatabase() {
|
|||||||
const schema = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/schema.sql`, "utf-8");
|
const schema = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/schema.sql`, "utf-8");
|
||||||
const demoFile = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/demo.zip`);
|
const demoFile = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/demo.zip`);
|
||||||
|
|
||||||
let rootNote;
|
let rootNote!: BNote;
|
||||||
|
|
||||||
sql.transactional(() => {
|
sql.transactional(() => {
|
||||||
log.info("Creating database schema ...");
|
log.info("Creating database schema ...");
|
||||||
@ -63,9 +67,6 @@ async function createInitialDatabase() {
|
|||||||
|
|
||||||
require('../becca/becca_loader').load();
|
require('../becca/becca_loader').load();
|
||||||
|
|
||||||
const BNote = require('../becca/entities/bnote');
|
|
||||||
const BBranch = require('../becca/entities/bbranch');
|
|
||||||
|
|
||||||
log.info("Creating root note ...");
|
log.info("Creating root note ...");
|
||||||
|
|
||||||
rootNote = new BNote({
|
rootNote = new BNote({
|
||||||
@ -84,8 +85,6 @@ async function createInitialDatabase() {
|
|||||||
notePosition: 10
|
notePosition: 10
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
const optionsInitService = require('./options_init');
|
|
||||||
|
|
||||||
optionsInitService.initDocumentOptions();
|
optionsInitService.initDocumentOptions();
|
||||||
optionsInitService.initNotSyncedOptions(true, {});
|
optionsInitService.initNotSyncedOptions(true, {});
|
||||||
optionsInitService.initStartupOptions();
|
optionsInitService.initStartupOptions();
|
||||||
@ -96,7 +95,6 @@ async function createInitialDatabase() {
|
|||||||
|
|
||||||
const dummyTaskContext = new TaskContext("no-progress-reporting", 'import', false);
|
const dummyTaskContext = new TaskContext("no-progress-reporting", 'import', false);
|
||||||
|
|
||||||
const zipImportService = require('./import/zip');
|
|
||||||
await zipImportService.importZip(dummyTaskContext, demoFile, rootNote);
|
await zipImportService.importZip(dummyTaskContext, demoFile, rootNote);
|
||||||
|
|
||||||
sql.transactional(() => {
|
sql.transactional(() => {
|
||||||
@ -106,7 +104,6 @@ async function createInitialDatabase() {
|
|||||||
|
|
||||||
const startNoteId = sql.getValue("SELECT noteId FROM branches WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition");
|
const startNoteId = sql.getValue("SELECT noteId FROM branches WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition");
|
||||||
|
|
||||||
const optionService = require('./options');
|
|
||||||
optionService.setOption('openNoteContexts', JSON.stringify([
|
optionService.setOption('openNoteContexts', JSON.stringify([
|
||||||
{
|
{
|
||||||
notePath: startNoteId,
|
notePath: startNoteId,
|
||||||
|
@ -19,6 +19,8 @@ import entityConstructor from "../becca/entity_constructor.js";
|
|||||||
import becca from "../becca/becca.js";
|
import becca from "../becca/becca.js";
|
||||||
import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface';
|
import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface';
|
||||||
import { CookieJar, ExecOpts } from './request_interface';
|
import { CookieJar, ExecOpts } from './request_interface';
|
||||||
|
import setupService from "./setup.js";
|
||||||
|
import consistency_checks from "./consistency_checks.js";
|
||||||
|
|
||||||
let proxyToggle = true;
|
let proxyToggle = true;
|
||||||
|
|
||||||
@ -107,8 +109,6 @@ async function sync() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function login() {
|
async function login() {
|
||||||
const setupService = require('./setup'); // circular dependency issue
|
|
||||||
|
|
||||||
if (!await setupService.hasSyncServerSchemaAndSeed()) {
|
if (!await setupService.hasSyncServerSchemaAndSeed()) {
|
||||||
await setupService.sendSeedToSyncServer();
|
await setupService.sendSeedToSyncServer();
|
||||||
}
|
}
|
||||||
@ -282,8 +282,7 @@ async function checkContentHash(syncContext: SyncContext) {
|
|||||||
|
|
||||||
if (failedChecks.length > 0) {
|
if (failedChecks.length > 0) {
|
||||||
// before re-queuing sectors, make sure the entity changes are correct
|
// before re-queuing sectors, make sure the entity changes are correct
|
||||||
const consistencyChecks = require('./consistency_checks');
|
consistency_checks.runEntityChangesChecks();
|
||||||
consistencyChecks.runEntityChangesChecks();
|
|
||||||
|
|
||||||
await syncRequest(syncContext, 'POST', `/api/sync/check-entity-changes`);
|
await syncRequest(syncContext, 'POST', `/api/sync/check-entity-changes`);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* (like consistency checks) can use this mutex to make sure sync isn't currently running.
|
* (like consistency checks) can use this mutex to make sure sync isn't currently running.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Mutex = require('async-mutex').Mutex;
|
import { Mutex } from "async-mutex";
|
||||||
const instance = new Mutex();
|
const instance = new Mutex();
|
||||||
|
|
||||||
async function doExclusively<T>(func: () => T) {
|
async function doExclusively<T>(func: () => T) {
|
||||||
|
@ -7,7 +7,13 @@ import entityChangesService from "./entity_changes.js";
|
|||||||
import becca from "../becca/becca.js";
|
import becca from "../becca/becca.js";
|
||||||
import BNote from "../becca/entities/bnote.js";
|
import BNote from "../becca/entities/bnote.js";
|
||||||
|
|
||||||
function validateParentChild(parentNoteId: string, childNoteId: string, branchId: string | null = null) {
|
interface ValidationResponse {
|
||||||
|
branch: BBranch | null;
|
||||||
|
success: boolean;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateParentChild(parentNoteId: string, childNoteId: string, branchId: string | null = null): ValidationResponse {
|
||||||
if (['root', '_hidden', '_share', '_lbRoot', '_lbAvailableLaunchers', '_lbVisibleLaunchers'].includes(childNoteId)) {
|
if (['root', '_hidden', '_share', '_lbRoot', '_lbAvailableLaunchers', '_lbVisibleLaunchers'].includes(childNoteId)) {
|
||||||
return { branch: null, success: false, message: `Cannot change this note's location.` };
|
return { branch: null, success: false, message: `Cannot change this note's location.` };
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
const randtoken = require('rand-token').generator({source: 'crypto'});
|
import { generator } from "rand-token";
|
||||||
import unescape from "unescape";
|
import unescape from "unescape";
|
||||||
import escape from "escape-html";
|
import escape from "escape-html";
|
||||||
import sanitize from "sanitize-filename";
|
import sanitize from "sanitize-filename";
|
||||||
import mimeTypes from "mime-types";
|
import mimeTypes from "mime-types";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
|
const randtoken = generator({source: 'crypto'});
|
||||||
|
|
||||||
function newEntityId() {
|
function newEntityId() {
|
||||||
return randomString(12);
|
return randomString(12);
|
||||||
}
|
}
|
||||||
@ -173,7 +175,7 @@ function replaceAll(string: string, replaceWhat: string, replaceWith: string) {
|
|||||||
return string.replace(new RegExp(quotedReplaceWhat, "g"), replaceWith);
|
return string.replace(new RegExp(quotedReplaceWhat, "g"), replaceWith);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDownloadTitle(fileName: string, type: string, mime: string) {
|
function formatDownloadTitle(fileName: string, type: string | null, mime: string) {
|
||||||
if (!fileName) {
|
if (!fileName) {
|
||||||
fileName = "untitled";
|
fileName = "untitled";
|
||||||
}
|
}
|
||||||
@ -182,7 +184,7 @@ function formatDownloadTitle(fileName: string, type: string, mime: string) {
|
|||||||
|
|
||||||
if (type === 'text') {
|
if (type === 'text') {
|
||||||
return `${fileName}.html`;
|
return `${fileName}.html`;
|
||||||
} else if (['relationMap', 'canvas', 'search'].includes(type)) {
|
} else if (type && ['relationMap', 'canvas', 'search'].includes(type)) {
|
||||||
return `${fileName}.json`;
|
return `${fileName}.json`;
|
||||||
} else {
|
} else {
|
||||||
if (!mime) {
|
if (!mime) {
|
||||||
|
@ -15,6 +15,7 @@ import log from "../services/log.js";
|
|||||||
import SNote from "./shaca/entities/snote.js";
|
import SNote from "./shaca/entities/snote.js";
|
||||||
import SBranch from "./shaca/entities/sbranch.js";
|
import SBranch from "./shaca/entities/sbranch.js";
|
||||||
import SAttachment from "./shaca/entities/sattachment.js";
|
import SAttachment from "./shaca/entities/sattachment.js";
|
||||||
|
import utils from "../services/utils.js";
|
||||||
|
|
||||||
function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } {
|
function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } {
|
||||||
if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
||||||
@ -249,8 +250,6 @@ function register(router: Router) {
|
|||||||
|
|
||||||
addNoIndexHeader(note, res);
|
addNoIndexHeader(note, res);
|
||||||
|
|
||||||
const utils = require('../services/utils');
|
|
||||||
|
|
||||||
const filename = utils.formatDownloadTitle(note.title, note.type, note.mime);
|
const filename = utils.formatDownloadTitle(note.title, note.type, note.mime);
|
||||||
|
|
||||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||||
@ -317,8 +316,6 @@ function register(router: Router) {
|
|||||||
|
|
||||||
addNoIndexHeader(attachment.note, res);
|
addNoIndexHeader(attachment.note, res);
|
||||||
|
|
||||||
const utils = require('../services/utils');
|
|
||||||
|
|
||||||
const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime);
|
const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime);
|
||||||
|
|
||||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
import AbstractShacaEntity from "./abstract_shaca_entity";
|
||||||
import { SAttributeRow } from "./rows";
|
import { SAttributeRow } from "./rows";
|
||||||
import SNote from "./snote.js";
|
import SNote from "./snote.js";
|
||||||
|
|
||||||
const AbstractShacaEntity = require('./abstract_shaca_entity');
|
|
||||||
|
|
||||||
class SAttribute extends AbstractShacaEntity {
|
class SAttribute extends AbstractShacaEntity {
|
||||||
|
|
||||||
attributeId: string;
|
attributeId: string;
|
||||||
|
@ -27,7 +27,7 @@ class SNote extends AbstractShacaEntity {
|
|||||||
parentBranches: SBranch[];
|
parentBranches: SBranch[];
|
||||||
parents: SNote[];
|
parents: SNote[];
|
||||||
children: SNote[];
|
children: SNote[];
|
||||||
private ownedAttributes: SAttribute[];
|
ownedAttributes: SAttribute[];
|
||||||
private __attributeCache: SAttribute[] | null;
|
private __attributeCache: SAttribute[] | null;
|
||||||
private __inheritableAttributeCache: SAttribute[] | null;
|
private __inheritableAttributeCache: SAttribute[] | null;
|
||||||
targetRelations: SAttribute[];
|
targetRelations: SAttribute[];
|
||||||
|
@ -8,7 +8,7 @@ export default class Shaca {
|
|||||||
notes!: Record<string, SNote>;
|
notes!: Record<string, SNote>;
|
||||||
branches!: Record<string, SBranch>;
|
branches!: Record<string, SBranch>;
|
||||||
childParentToBranch!: Record<string, SBranch>;
|
childParentToBranch!: Record<string, SBranch>;
|
||||||
private attributes!: Record<string, SAttribute>;
|
attributes!: Record<string, SAttribute>;
|
||||||
attachments!: Record<string, SAttachment>;
|
attachments!: Record<string, SAttachment>;
|
||||||
aliasToNote!: Record<string, SNote>;
|
aliasToNote!: Record<string, SNote>;
|
||||||
shareRootNote!: SNote | null;
|
shareRootNote!: SNote | null;
|
||||||
|
38
src/www.ts
38
src/www.ts
@ -1,23 +1,4 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
// setup basic error handling even before requiring dependencies, since those can produce errors as well
|
|
||||||
|
|
||||||
process.on('unhandledRejection', error => {
|
|
||||||
// this makes sure that stacktrace of failed promise is printed out
|
|
||||||
console.log(error);
|
|
||||||
|
|
||||||
// but also try to log it into file
|
|
||||||
require('./services/log').info(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
function exit() {
|
|
||||||
console.log("Caught interrupt/termination signal. Exiting.");
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
process.on('SIGINT', exit);
|
|
||||||
process.on('SIGTERM', exit);
|
|
||||||
|
|
||||||
import app from "./app.js";
|
import app from "./app.js";
|
||||||
import sessionParser from "./routes/session_parser.js";
|
import sessionParser from "./routes/session_parser.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@ -32,6 +13,25 @@ import port from "./services/port.js";
|
|||||||
import host from "./services/host.js";
|
import host from "./services/host.js";
|
||||||
import semver from "semver";
|
import semver from "semver";
|
||||||
|
|
||||||
|
// setup basic error handling even before requiring dependencies, since those can produce errors as well
|
||||||
|
|
||||||
|
process.on('unhandledRejection', (error: Error) => {
|
||||||
|
// this makes sure that stacktrace of failed promise is printed out
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
// but also try to log it into file
|
||||||
|
log.info(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
function exit() {
|
||||||
|
console.log("Caught interrupt/termination signal. Exiting.");
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGINT', exit);
|
||||||
|
process.on('SIGTERM', exit);
|
||||||
|
|
||||||
|
|
||||||
if (!semver.satisfies(process.version, ">=10.5.0")) {
|
if (!semver.satisfies(process.version, ">=10.5.0")) {
|
||||||
console.error("Trilium only supports node.js 10.5 and later");
|
console.error("Trilium only supports node.js 10.5 and later");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user