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";
|
||||
|
||||
import electron from "electron";
|
||||
import electronDebug from "electron-debug";
|
||||
import electronDl from "electron-dl";
|
||||
import sqlInit from "./src/services/sql_init.js";
|
||||
import appIconService from "./src/services/app_icon.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
|
||||
require('electron-debug')();
|
||||
electronDebug();
|
||||
|
||||
appIconService.installLocalAppIcon();
|
||||
|
||||
require('electron-dl')({ saveAs: true });
|
||||
electronDl({ saveAs: true });
|
||||
|
||||
// needed for excalidraw export https://github.com/zadam/trilium/issues/4271
|
||||
electron.app.commandLine.appendSwitch(
|
||||
|
11
package-lock.json
generated
11
package-lock.json
generated
@ -111,6 +111,7 @@
|
||||
"@types/sax": "^1.2.7",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/serve-favicon": "^2.5.7",
|
||||
"@types/session-file-store": "^1.2.5",
|
||||
"@types/stream-throttle": "^0.1.4",
|
||||
"@types/tmp": "^0.2.6",
|
||||
"@types/turndown": "^5.0.4",
|
||||
@ -2614,6 +2615,16 @@
|
||||
"@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": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/stream-throttle/-/stream-throttle-0.1.4.tgz",
|
||||
|
@ -144,6 +144,7 @@
|
||||
"@types/sax": "^1.2.7",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/serve-favicon": "^2.5.7",
|
||||
"@types/session-file-store": "^1.2.5",
|
||||
"@types/stream-throttle": "^0.1.4",
|
||||
"@types/tmp": "^0.2.6",
|
||||
"@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", () => {
|
||||
it("handles parens", () => {
|
||||
const input = ["(", "hello", ")", "and", "(", "(", "pick", "one", ")", "and", "another", ")"]
|
||||
.map(token => ({token}));
|
||||
|
||||
expect(handleParens(input))
|
||||
.toEqual([
|
||||
const actual: TokenStructure = [
|
||||
[
|
||||
{token: "hello"}
|
||||
],
|
||||
{token: "and"},
|
||||
[
|
||||
[
|
||||
{token: "hello"}
|
||||
{token: "pick"},
|
||||
{token: "one"}
|
||||
],
|
||||
{token: "and"},
|
||||
[
|
||||
[
|
||||
{token: "pick"},
|
||||
{token: "one"}
|
||||
],
|
||||
{token: "and"},
|
||||
{token: "another"}
|
||||
]
|
||||
]);
|
||||
{token: "another"}
|
||||
]
|
||||
];
|
||||
|
||||
expect(handleParens(input)).toEqual(actual);
|
||||
});
|
||||
});
|
||||
|
@ -155,9 +155,7 @@ export default class Becca {
|
||||
}
|
||||
|
||||
getRevision(revisionId: string): BRevision | null {
|
||||
const row = sql.getRow("SELECT * FROM revisions WHERE revisionId = ?", [revisionId]);
|
||||
|
||||
const BRevision = require('./entities/brevision'); // avoiding circular dependency problems
|
||||
const row = sql.getRow<RevisionRow | null>("SELECT * FROM revisions WHERE revisionId = ?", [revisionId]);
|
||||
return row ? new BRevision(row) : null;
|
||||
}
|
||||
|
||||
@ -179,9 +177,7 @@ export default class Becca {
|
||||
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(query, [attachmentId])
|
||||
return sql.getRows<AttachmentRow>(query, [attachmentId])
|
||||
.map(row => new BAttachment(row))[0];
|
||||
}
|
||||
|
||||
@ -194,7 +190,6 @@ export default class Becca {
|
||||
}
|
||||
|
||||
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)
|
||||
.map(row => new BAttachment(row));
|
||||
}
|
||||
@ -204,9 +199,7 @@ export default class Becca {
|
||||
return null;
|
||||
}
|
||||
|
||||
const row = sql.getRow("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [entity.blobId]);
|
||||
|
||||
const BBlob = require('./entities/bblob'); // avoiding circular dependency problems
|
||||
const row = sql.getRow<BBlob | null>("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [entity.blobId]);
|
||||
return row ? new BBlob(row) : null;
|
||||
}
|
||||
|
||||
@ -248,16 +241,12 @@ export default class Becca {
|
||||
}
|
||||
|
||||
getRecentNotesFromQuery(query: string, params: string[] = []): BRecentNote[] {
|
||||
const rows = sql.getRows(query, params);
|
||||
|
||||
const BRecentNote = require('./entities/brecent_note'); // avoiding circular dependency problems
|
||||
const rows = sql.getRows<BRecentNote>(query, params);
|
||||
return rows.map(row => new BRecentNote(row));
|
||||
}
|
||||
|
||||
getRevisionsFromQuery(query: string, params: string[] = []): BRevision[] {
|
||||
const rows = sql.getRows<RevisionRow>(query, params);
|
||||
|
||||
const BRevision = require('./entities/brevision'); // avoiding circular dependency problems
|
||||
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 { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from './entities/rows';
|
||||
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) => {
|
||||
sqlInit.dbReady.then(() => {
|
||||
cls.init(() => {
|
||||
load();
|
||||
|
||||
require('../services/options_init').initStartupOptions();
|
||||
options_init.initStartupOptions();
|
||||
|
||||
res();
|
||||
});
|
||||
@ -73,7 +75,7 @@ function load() {
|
||||
function reload(reason: string) {
|
||||
load();
|
||||
|
||||
require('../services/ws').reloadFrontend(reason || "becca reloaded");
|
||||
ws.reloadFrontend(reason || "becca reloaded");
|
||||
}
|
||||
|
||||
eventService.subscribeBeccaLoader([eventService.ENTITY_CHANGE_SYNCED], ({ entityName, entityRow }) => {
|
||||
|
@ -9,6 +9,7 @@ import log from "../../services/log.js";
|
||||
import { AttachmentRow } from './rows';
|
||||
import BNote from "./bnote.js";
|
||||
import BBranch from "./bbranch.js";
|
||||
import noteService from "../../services/notes.js";
|
||||
|
||||
const attachmentRoleToNoteTypeMapping = {
|
||||
'image': 'image',
|
||||
@ -157,8 +158,6 @@ class BAttachment extends AbstractBeccaEntity<BAttachment> {
|
||||
throw new Error(`Cannot convert protected attachment outside of protected session`);
|
||||
}
|
||||
|
||||
const noteService = require('../../services/notes');
|
||||
|
||||
const { note, branch } = noteService.createNewNote({
|
||||
parentNoteId: this.ownerId,
|
||||
title: this.title,
|
||||
|
@ -8,6 +8,7 @@ import TaskContext from "../../services/task_context.js";
|
||||
import cls from "../../services/cls.js";
|
||||
import log from "../../services/log.js";
|
||||
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
|
||||
@ -157,7 +158,6 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
|
||||
|
||||
if (parentBranches.length === 1 && parentBranches[0] === this) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,14 @@ import TaskContext from "../../services/task_context.js";
|
||||
import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
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 BAttribute from "./battribute.js";
|
||||
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);
|
||||
|
||||
const LABEL = 'label';
|
||||
@ -890,11 +894,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
}
|
||||
|
||||
try {
|
||||
const searchService = require('../../services/search/services/search');
|
||||
const {searchResultNoteIds} = searchService.searchFromNote(this);
|
||||
|
||||
const result = searchService.searchFromNote(this);
|
||||
const becca = this.becca;
|
||||
return (searchResultNoteIds as string[]) // TODO: remove cast once search is converted
|
||||
return (result.searchResultNoteIds)
|
||||
.map(resultNoteId => becca.notes[resultNoteId])
|
||||
.filter(note => !!note);
|
||||
}
|
||||
@ -1261,7 +1263,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
* @param name - attribute name
|
||||
* @param value - attribute value (optional)
|
||||
*/
|
||||
setAttribute(type: string, name: string, value?: string) {
|
||||
setAttribute(type: AttributeType, name: string, value?: string) {
|
||||
const attributes = this.getOwnedAttributes();
|
||||
const attr = attributes.find(attr => attr.type === type && attr.name === name);
|
||||
|
||||
@ -1274,8 +1276,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
}
|
||||
}
|
||||
else {
|
||||
const BAttribute = require('./battribute');
|
||||
|
||||
new BAttribute({
|
||||
noteId: this.noteId,
|
||||
type: type,
|
||||
@ -1310,9 +1310,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
* @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.
|
||||
*/
|
||||
addAttribute(type: string, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute {
|
||||
const BAttribute = require('./battribute');
|
||||
|
||||
addAttribute(type: AttributeType, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute {
|
||||
return new BAttribute({
|
||||
noteId: this.noteId,
|
||||
type: type,
|
||||
@ -1351,7 +1349,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
* @param name - attribute name
|
||||
* @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) {
|
||||
this.setAttribute(type, name, value);
|
||||
}
|
||||
@ -1423,8 +1421,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
}
|
||||
|
||||
searchNotesInSubtree(searchString: string) {
|
||||
const searchService = require('../../services/search/services/search');
|
||||
|
||||
return searchService.searchNotes(searchString) as BNote[];
|
||||
}
|
||||
|
||||
@ -1432,12 +1428,16 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
return this.searchNotesInSubtree(searchString)[0];
|
||||
}
|
||||
|
||||
cloneTo(parentNoteId: string) {
|
||||
const cloningService = require('../../services/cloning');
|
||||
|
||||
cloneTo(parentNoteId: string): CloneResponse {
|
||||
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 }) {
|
||||
@ -1508,7 +1508,6 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
|
||||
parentNote.setContent(fixedContent);
|
||||
|
||||
const noteService = require('../../services/notes');
|
||||
noteService.asyncPostProcessContent(parentNote, fixedContent); // to mark an unused attachment for deletion
|
||||
|
||||
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
|
||||
const handlers = require('../../services/handlers');
|
||||
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
|
||||
taskContext.noteDeletionHandlerTriggered = true;
|
||||
|
||||
|
@ -8,6 +8,7 @@ import AbstractBeccaEntity from "./abstract_becca_entity.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import BAttachment from "./battachment.js";
|
||||
import { AttachmentRow, RevisionRow } from './rows';
|
||||
import eraseService from "../../services/erase.js";
|
||||
|
||||
interface ContentOpts {
|
||||
/** 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).
|
||||
*/
|
||||
eraseRevision() {
|
||||
require('../../services/erase.js').eraseRevisions([this.revisionId]);
|
||||
if (this.revisionId) {
|
||||
eraseService.eraseRevisions([this.revisionId]);
|
||||
}
|
||||
}
|
||||
|
||||
beforeSaving() {
|
||||
|
@ -42,7 +42,7 @@ export interface OptionRow {
|
||||
name: string;
|
||||
value: string;
|
||||
isSynced: boolean;
|
||||
utcDateModified: string;
|
||||
utcDateModified?: string;
|
||||
}
|
||||
|
||||
export interface EtapiTokenRow {
|
||||
@ -69,7 +69,7 @@ export interface AttributeRow {
|
||||
noteId?: string;
|
||||
type: AttributeType;
|
||||
name: string;
|
||||
position?: number;
|
||||
position?: number | null;
|
||||
value?: string;
|
||||
isInheritable?: boolean;
|
||||
utcDateModified?: string;
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
import imageService from "../../services/image.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
|
||||
import fs from "fs";
|
||||
import { Request, Response } from 'express';
|
||||
import BNote from "../../becca/entities/bnote.js";
|
||||
import BRevision from "../../becca/entities/brevision.js";
|
||||
import { AppRequest } from '../route-interface';
|
||||
import { RESOURCE_DIR } from "../../services/resource_dir.js";
|
||||
|
||||
function returnImageFromNote(req: Request, res: Response) {
|
||||
const image = becca.getNote(req.params.noteId);
|
||||
|
@ -4,19 +4,19 @@ import { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.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 cls from "../../services/cls.js";
|
||||
import attributeFormatter from "../../services/attribute_formatter.js";
|
||||
import ValidationError from "../../errors/validation_error.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);
|
||||
|
||||
if (!note) {
|
||||
// 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') {
|
||||
|
@ -14,6 +14,7 @@ import ws from "../../services/ws.js";
|
||||
import { Request } from 'express';
|
||||
import { EntityChange, EntityChangeRecord } from '../../services/entity_changes_interface';
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import consistencyChecksService from "../../services/consistency_checks.js";
|
||||
|
||||
async function testSync() {
|
||||
try {
|
||||
@ -206,7 +207,7 @@ function queueSector(req: Request) {
|
||||
}
|
||||
|
||||
function checkEntityChanges() {
|
||||
require('../../services/consistency_checks').runEntityChangesChecks();
|
||||
consistencyChecksService.runEntityChangesChecks();
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import session from "express-session";
|
||||
import sessionFileStore from "session-file-store";
|
||||
import sessionSecret from "../services/session_secret.js";
|
||||
import dataDir from "../services/data_dir.js";
|
||||
const FileStore = require('session-file-store')(session);
|
||||
const FileStore = sessionFileStore(session);
|
||||
|
||||
const sessionParser = session({
|
||||
secret: sessionSecret,
|
||||
|
@ -111,7 +111,7 @@ const ACTION_HANDLERS: Record<string, ActionHandler> = {
|
||||
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)}`);
|
||||
}
|
||||
},
|
||||
|
@ -1,18 +1,28 @@
|
||||
"use strict";
|
||||
|
||||
const sql = require('./sql');
|
||||
const eventChangesService = require('./entity_changes');
|
||||
const treeService = require('./tree');
|
||||
const BBranch = require('../becca/entities/bbranch');
|
||||
const becca = require('../becca/becca');
|
||||
const log = require('./log');
|
||||
import sql from './sql';
|
||||
import eventChangesService from './entity_changes';
|
||||
import treeService from './tree';
|
||||
import BBranch from '../becca/entities/bbranch';
|
||||
import becca from '../becca/becca';
|
||||
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)) {
|
||||
return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' };
|
||||
}
|
||||
|
||||
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') {
|
||||
return {
|
||||
@ -31,7 +41,7 @@ function cloneNoteToParentNote(noteId: string, parentNoteId: string, prefix: str
|
||||
noteId: noteId,
|
||||
parentNoteId: parentNoteId,
|
||||
prefix: prefix,
|
||||
isExpanded: 0
|
||||
isExpanded: false
|
||||
}).save();
|
||||
|
||||
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);
|
||||
|
||||
if (!parentBranch) {
|
||||
@ -67,6 +77,9 @@ function ensureNoteIsPresentInParent(noteId: string, parentNoteId: string, prefi
|
||||
|
||||
const parentNote = becca.getNote(parentNoteId);
|
||||
|
||||
if (!parentNote) {
|
||||
return { branch: null, success: false, message: "Can't find parent note." };
|
||||
}
|
||||
if (parentNote.type === 'search') {
|
||||
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,
|
||||
parentNoteId: parentNoteId,
|
||||
prefix: prefix,
|
||||
isExpanded: 0
|
||||
isExpanded: false
|
||||
}).save();
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
if (branch) {
|
||||
@ -137,13 +150,13 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) {
|
||||
|
||||
if (!(noteId in becca.notes)) {
|
||||
return { success: false, message: `Note to be cloned '${noteId}' is deleted or does not exist.` };
|
||||
} else if (!(afterNote.parentNoteId in becca.notes)) {
|
||||
return { success: false, message: `After note '${afterNote.parentNoteId}' is deleted or does not exist.` };
|
||||
} else if (!afterNote || !(afterNote.parentNoteId in becca.notes)) {
|
||||
return { success: false, message: `After note '${afterNote?.parentNoteId}' is deleted or does not exist.` };
|
||||
}
|
||||
|
||||
const parentNote = becca.getNote(afterNote.parentNoteId);
|
||||
|
||||
if (parentNote.type === 'search') {
|
||||
if (!parentNote || parentNote.type === 'search') {
|
||||
return {
|
||||
success: false,
|
||||
message: "Can't clone into a search note"
|
||||
@ -167,7 +180,7 @@ function cloneNoteAfter(noteId: string, afterBranchId: string) {
|
||||
noteId: noteId,
|
||||
parentNoteId: afterNote.parentNoteId,
|
||||
notePosition: afterNote.notePosition + 10,
|
||||
isExpanded: 0
|
||||
isExpanded: false
|
||||
}).save();
|
||||
|
||||
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 { EntityChange } from './entity_changes_interface';
|
||||
import type { Blob } from "./blob-interface";
|
||||
import eventService from "./events.js";
|
||||
|
||||
let maxEntityChangeId = 0;
|
||||
|
||||
@ -57,8 +58,6 @@ function putNoteReorderingEntityChange(parentNoteId: string, componentId?: strin
|
||||
instanceId
|
||||
});
|
||||
|
||||
const eventService = require('./events');
|
||||
|
||||
eventService.emit(eventService.ENTITY_CHANGED, {
|
||||
entityName: 'note_reordering',
|
||||
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 ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION";
|
||||
|
@ -11,7 +11,6 @@ import protectedSessionService from "../protected_session.js";
|
||||
import sanitize from "sanitize-filename";
|
||||
import fs from "fs";
|
||||
import becca from "../../becca/becca.js";
|
||||
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
|
||||
import archiver from "archiver";
|
||||
import log from "../log.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 BBranch from "../../becca/entities/bbranch.js";
|
||||
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) {
|
||||
if (!['html', 'markdown'].includes(format)) {
|
||||
|
@ -156,7 +156,6 @@ function saveImageToAttachment(noteId: string, uploadBuffer: Buffer, originalNam
|
||||
setTimeout(() => {
|
||||
sql.transactional(() => {
|
||||
const note = becca.getNoteOrThrow(noteId);
|
||||
const noteService = require('../services/notes');
|
||||
noteService.asyncPostProcessContent(note, note.getContent()); // to mark an unused attachment for deletion
|
||||
});
|
||||
}, 5000);
|
||||
|
@ -12,6 +12,7 @@ import sanitizeAttributeName from "../sanitize_attribute_name.js";
|
||||
import TaskContext from "../task_context.js";
|
||||
import BNote from "../../becca/entities/bnote.js";
|
||||
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)
|
||||
@ -29,7 +30,7 @@ function parseDate(text: string) {
|
||||
}
|
||||
|
||||
interface Attribute {
|
||||
type: string;
|
||||
type: AttributeType;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ function checkDate(millisSinceMidnight: number) {
|
||||
return millisSinceMidnight;
|
||||
}
|
||||
|
||||
function log(str: string) {
|
||||
function log(str: string | Error) {
|
||||
const bundleNoteId = cls.get("bundleNoteId");
|
||||
|
||||
if (bundleNoteId) {
|
||||
@ -66,11 +66,11 @@ function log(str: string) {
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
function info(message: string) {
|
||||
function info(message: string | Error) {
|
||||
log(message);
|
||||
}
|
||||
|
||||
function error(message: string) {
|
||||
function error(message: string | Error) {
|
||||
log(`ERROR: ${message}`);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ import html2plaintext from "html2plaintext";
|
||||
import { AttachmentRow, AttributeRow, BranchRow, NoteRow, NoteType } from '../becca/entities/rows';
|
||||
import TaskContext from "./task_context.js";
|
||||
import { NoteParams } from './note-interface';
|
||||
import imageService from "./image.js";
|
||||
|
||||
interface FoundLink {
|
||||
name: "imageLink" | "internalLink" | "includeNoteLink" | "relationMapLink",
|
||||
@ -466,7 +467,7 @@ async function downloadImage(noteId: string, imageUrl: string) {
|
||||
const unescapedUrl = utils.unescapeHtml(imageUrl);
|
||||
|
||||
try {
|
||||
let imageBuffer;
|
||||
let imageBuffer: Buffer;
|
||||
|
||||
if (imageUrl.toLowerCase().startsWith("file://")) {
|
||||
imageBuffer = await new Promise((res, rej) => {
|
||||
@ -487,10 +488,13 @@ async function downloadImage(noteId: string, imageUrl: string) {
|
||||
const parsedUrl = url.parse(unescapedUrl);
|
||||
const title = path.basename(parsedUrl.pathname || "");
|
||||
|
||||
const imageService = require('../services/image');
|
||||
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}'`);
|
||||
}
|
||||
@ -520,7 +524,6 @@ function downloadImages(noteId: string, content: string) {
|
||||
const imageBase64 = url.substr(inlineImageMatch[0].length);
|
||||
const imageBuffer = Buffer.from(imageBase64, 'base64');
|
||||
|
||||
const imageService = require('../services/image');
|
||||
const attachment = imageService.saveImageToAttachment(noteId, imageBuffer, "inline image", true, true);
|
||||
|
||||
const encodedTitle = encodeURIComponent(attachment.title);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import becca from "../becca/becca.js";
|
||||
import BOption from "../becca/entities/boption.js";
|
||||
import { OptionRow } from '../becca/entities/rows';
|
||||
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) {
|
||||
// to avoid circular dependency, need to find a better solution
|
||||
const BOption = require('../becca/entities/boption');
|
||||
|
||||
function createOption(name: string, value: string, isSynced: boolean) {
|
||||
new BOption({
|
||||
name: name,
|
||||
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 opts: ClientOpts = {
|
||||
method: 'GET',
|
||||
@ -149,7 +149,7 @@ function getImage(imageUrl: string) {
|
||||
const proxyAgent = getProxyAgent(opts);
|
||||
const parsedTargetUrl = url.parse(opts.url);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<Buffer>((resolve, reject) => {
|
||||
try {
|
||||
const request = client.request({
|
||||
method: opts.method,
|
||||
@ -181,8 +181,7 @@ function getImage(imageUrl: string) {
|
||||
});
|
||||
|
||||
request.end(undefined);
|
||||
}
|
||||
catch (e: any) {
|
||||
} catch (e: any) {
|
||||
reject(generateError(opts, e.message));
|
||||
}
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ import log from "./log.js";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
const RESOURCE_DIR = path.resolve(__dirname, "../..");
|
||||
export const RESOURCE_DIR = path.resolve(__dirname, "../..");
|
||||
|
||||
// where the "trilium" executable is
|
||||
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
|
||||
*/
|
||||
function handleParens(tokens: (TokenData | TokenData[])[]) {
|
||||
function handleParens(tokens: TokenStructure) {
|
||||
if (tokens.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import utils from "../../utils.js";
|
||||
import TrueExp from "../expressions/true.js";
|
||||
import IsHiddenExp from "../expressions/is_hidden.js";
|
||||
import SearchContext from "../search_context.js";
|
||||
import { TokenData } from "./types";
|
||||
import { TokenData, TokenStructure } from "./types";
|
||||
import Expression from "../expressions/expression.js";
|
||||
|
||||
function getFulltext(_tokens: TokenData[], searchContext: SearchContext) {
|
||||
@ -448,7 +448,7 @@ function getExpression(tokens: TokenData[], searchContext: SearchContext, level
|
||||
|
||||
function parse({fulltextTokens, expressionTokens, searchContext}: {
|
||||
fulltextTokens: TokenData[],
|
||||
expressionTokens: (TokenData | TokenData[])[],
|
||||
expressionTokens: TokenStructure,
|
||||
searchContext: SearchContext,
|
||||
originalQuery: string
|
||||
}) {
|
||||
|
@ -13,11 +13,24 @@ import log from "../../log.js";
|
||||
import hoistedNoteService from "../../hoisted_note.js";
|
||||
import BNote from "../../../becca/entities/bnote.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 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 highlightedTokens: string[];
|
||||
|
||||
@ -78,7 +91,6 @@ function searchFromRelation(note: BNote, relationName: string) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const scriptService = require('../../script'); // TODO: to avoid circular dependency
|
||||
const result = scriptService.executeNote(scriptNote, {originEntity: note});
|
||||
|
||||
if (!Array.isArray(result)) {
|
||||
@ -273,7 +285,7 @@ function parseQueryToExpression(query: string, searchContext: SearchContext) {
|
||||
const {fulltextQuery, fulltextTokens, expressionTokens} = lex(query);
|
||||
searchContext.fulltextQuery = fulltextQuery;
|
||||
|
||||
let structuredExpressionTokens: (TokenData | TokenData[])[];
|
||||
let structuredExpressionTokens: TokenStructure;
|
||||
|
||||
try {
|
||||
structuredExpressionTokens = handleParens(expressionTokens);
|
||||
|
@ -1,3 +1,5 @@
|
||||
export type TokenStructure = (TokenData | TokenStructure)[];
|
||||
|
||||
export interface TokenData {
|
||||
token: string;
|
||||
inQuotes?: boolean;
|
||||
|
@ -10,6 +10,9 @@ import dataDir from "./data_dir.js";
|
||||
import cls from "./cls.js";
|
||||
import fs from "fs-extra";
|
||||
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);
|
||||
dbConnection.pragma('journal_mode = WAL');
|
||||
@ -248,7 +251,7 @@ function transactional<T>(func: (statement: Statement) => T) {
|
||||
const ret = (dbConnection.transaction(func) as any).deferred();
|
||||
|
||||
if (!dbConnection.inTransaction) { // i.e. transaction was really committed (and not just savepoint released)
|
||||
require('./ws').sendTransactionEntityChangesToAllClients();
|
||||
ws.sendTransactionEntityChangesToAllClients();
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -259,11 +262,11 @@ function transactional<T>(func: (statement: Statement) => T) {
|
||||
if (entityChangeIds.length > 0) {
|
||||
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
|
||||
require('./entity_changes').recalculateMaxEntityChangeId();
|
||||
entity_changes.recalculateMaxEntityChangeId();
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
@ -11,6 +11,10 @@ import migrationService from "./migration.js";
|
||||
import cls from "./cls.js";
|
||||
import config from "./config.js";
|
||||
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>();
|
||||
|
||||
@ -54,7 +58,7 @@ async function createInitialDatabase() {
|
||||
const schema = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/schema.sql`, "utf-8");
|
||||
const demoFile = fs.readFileSync(`${resourceDir.DB_INIT_DIR}/demo.zip`);
|
||||
|
||||
let rootNote;
|
||||
let rootNote!: BNote;
|
||||
|
||||
sql.transactional(() => {
|
||||
log.info("Creating database schema ...");
|
||||
@ -63,9 +67,6 @@ async function createInitialDatabase() {
|
||||
|
||||
require('../becca/becca_loader').load();
|
||||
|
||||
const BNote = require('../becca/entities/bnote');
|
||||
const BBranch = require('../becca/entities/bbranch');
|
||||
|
||||
log.info("Creating root note ...");
|
||||
|
||||
rootNote = new BNote({
|
||||
@ -84,8 +85,6 @@ async function createInitialDatabase() {
|
||||
notePosition: 10
|
||||
}).save();
|
||||
|
||||
const optionsInitService = require('./options_init');
|
||||
|
||||
optionsInitService.initDocumentOptions();
|
||||
optionsInitService.initNotSyncedOptions(true, {});
|
||||
optionsInitService.initStartupOptions();
|
||||
@ -96,7 +95,6 @@ async function createInitialDatabase() {
|
||||
|
||||
const dummyTaskContext = new TaskContext("no-progress-reporting", 'import', false);
|
||||
|
||||
const zipImportService = require('./import/zip');
|
||||
await zipImportService.importZip(dummyTaskContext, demoFile, rootNote);
|
||||
|
||||
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 optionService = require('./options');
|
||||
optionService.setOption('openNoteContexts', JSON.stringify([
|
||||
{
|
||||
notePath: startNoteId,
|
||||
|
@ -19,6 +19,8 @@ import entityConstructor from "../becca/entity_constructor.js";
|
||||
import becca from "../becca/becca.js";
|
||||
import { EntityChange, EntityChangeRecord, EntityRow } from './entity_changes_interface';
|
||||
import { CookieJar, ExecOpts } from './request_interface';
|
||||
import setupService from "./setup.js";
|
||||
import consistency_checks from "./consistency_checks.js";
|
||||
|
||||
let proxyToggle = true;
|
||||
|
||||
@ -107,8 +109,6 @@ async function sync() {
|
||||
}
|
||||
|
||||
async function login() {
|
||||
const setupService = require('./setup'); // circular dependency issue
|
||||
|
||||
if (!await setupService.hasSyncServerSchemaAndSeed()) {
|
||||
await setupService.sendSeedToSyncServer();
|
||||
}
|
||||
@ -282,8 +282,7 @@ async function checkContentHash(syncContext: SyncContext) {
|
||||
|
||||
if (failedChecks.length > 0) {
|
||||
// before re-queuing sectors, make sure the entity changes are correct
|
||||
const consistencyChecks = require('./consistency_checks');
|
||||
consistencyChecks.runEntityChangesChecks();
|
||||
consistency_checks.runEntityChangesChecks();
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
const Mutex = require('async-mutex').Mutex;
|
||||
import { Mutex } from "async-mutex";
|
||||
const instance = new Mutex();
|
||||
|
||||
async function doExclusively<T>(func: () => T) {
|
||||
|
@ -7,7 +7,13 @@ import entityChangesService from "./entity_changes.js";
|
||||
import becca from "../becca/becca.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)) {
|
||||
return { branch: null, success: false, message: `Cannot change this note's location.` };
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
import crypto from "crypto";
|
||||
const randtoken = require('rand-token').generator({source: 'crypto'});
|
||||
import { generator } from "rand-token";
|
||||
import unescape from "unescape";
|
||||
import escape from "escape-html";
|
||||
import sanitize from "sanitize-filename";
|
||||
import mimeTypes from "mime-types";
|
||||
import path from "path";
|
||||
|
||||
const randtoken = generator({source: 'crypto'});
|
||||
|
||||
function newEntityId() {
|
||||
return randomString(12);
|
||||
}
|
||||
@ -173,7 +175,7 @@ function replaceAll(string: string, replaceWhat: string, replaceWith: string) {
|
||||
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) {
|
||||
fileName = "untitled";
|
||||
}
|
||||
@ -182,7 +184,7 @@ function formatDownloadTitle(fileName: string, type: string, mime: string) {
|
||||
|
||||
if (type === 'text') {
|
||||
return `${fileName}.html`;
|
||||
} else if (['relationMap', 'canvas', 'search'].includes(type)) {
|
||||
} else if (type && ['relationMap', 'canvas', 'search'].includes(type)) {
|
||||
return `${fileName}.json`;
|
||||
} else {
|
||||
if (!mime) {
|
||||
|
@ -15,6 +15,7 @@ import log from "../services/log.js";
|
||||
import SNote from "./shaca/entities/snote.js";
|
||||
import SBranch from "./shaca/entities/sbranch.js";
|
||||
import SAttachment from "./shaca/entities/sattachment.js";
|
||||
import utils from "../services/utils.js";
|
||||
|
||||
function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } {
|
||||
if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
|
||||
@ -249,8 +250,6 @@ function register(router: Router) {
|
||||
|
||||
addNoIndexHeader(note, res);
|
||||
|
||||
const utils = require('../services/utils');
|
||||
|
||||
const filename = utils.formatDownloadTitle(note.title, note.type, note.mime);
|
||||
|
||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||
@ -317,8 +316,6 @@ function register(router: Router) {
|
||||
|
||||
addNoIndexHeader(attachment.note, res);
|
||||
|
||||
const utils = require('../services/utils');
|
||||
|
||||
const filename = utils.formatDownloadTitle(attachment.title, null, attachment.mime);
|
||||
|
||||
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
|
||||
|
@ -1,10 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
import AbstractShacaEntity from "./abstract_shaca_entity";
|
||||
import { SAttributeRow } from "./rows";
|
||||
import SNote from "./snote.js";
|
||||
|
||||
const AbstractShacaEntity = require('./abstract_shaca_entity');
|
||||
|
||||
class SAttribute extends AbstractShacaEntity {
|
||||
|
||||
attributeId: string;
|
||||
|
@ -27,7 +27,7 @@ class SNote extends AbstractShacaEntity {
|
||||
parentBranches: SBranch[];
|
||||
parents: SNote[];
|
||||
children: SNote[];
|
||||
private ownedAttributes: SAttribute[];
|
||||
ownedAttributes: SAttribute[];
|
||||
private __attributeCache: SAttribute[] | null;
|
||||
private __inheritableAttributeCache: SAttribute[] | null;
|
||||
targetRelations: SAttribute[];
|
||||
|
@ -8,7 +8,7 @@ export default class Shaca {
|
||||
notes!: Record<string, SNote>;
|
||||
branches!: Record<string, SBranch>;
|
||||
childParentToBranch!: Record<string, SBranch>;
|
||||
private attributes!: Record<string, SAttribute>;
|
||||
attributes!: Record<string, SAttribute>;
|
||||
attachments!: Record<string, SAttachment>;
|
||||
aliasToNote!: Record<string, SNote>;
|
||||
shareRootNote!: SNote | null;
|
||||
|
38
src/www.ts
38
src/www.ts
@ -1,23 +1,4 @@
|
||||
#!/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 sessionParser from "./routes/session_parser.js";
|
||||
import fs from "fs";
|
||||
@ -32,6 +13,25 @@ import port from "./services/port.js";
|
||||
import host from "./services/host.js";
|
||||
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")) {
|
||||
console.error("Trilium only supports node.js 10.5 and later");
|
||||
process.exit(1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user