Unverified Commit 7fde587a authored by NGPixel's avatar NGPixel

fix: file manager rename + ltree path encode/decode + various improvements

parent b8a44d99
import { get, has, isEmpty, isPlainObject } from 'lodash-es' import { create, get, has, isEmpty, isPlainObject } from 'lodash-es'
import path from 'node:path' import path from 'node:path'
import knex from 'knex' import knex from 'knex'
import fs from 'node:fs/promises' import fs from 'node:fs/promises'
import Objection from 'objection' import Objection from 'objection'
import PGPubSub from 'pg-pubsub' import PGPubSub from 'pg-pubsub'
import semver from 'semver'
import { createDeferred } from '../helpers/common.mjs'
import migrationSource from '../db/migrator-source.mjs' import migrationSource from '../db/migrator-source.mjs'
// const migrateFromLegacy = require('../db/legacy') // const migrateFromLegacy = require('../db/legacy')
import { setTimeout } from 'node:timers/promises' import { setTimeout } from 'node:timers/promises'
...@@ -17,12 +19,14 @@ export default { ...@@ -17,12 +19,14 @@ export default {
knex: null, knex: null,
listener: null, listener: null,
config: null, config: null,
VERSION: null,
LEGACY: false,
onReady: createDeferred(),
connectAttempts: 0,
/** /**
* Initialize DB * Initialize DB
*/ */
async init (workerMode = false) { async init (workerMode = false) {
let self = this
WIKI.logger.info('Checking DB configuration...') WIKI.logger.info('Checking DB configuration...')
// Fetch DB Config // Fetch DB Config
...@@ -101,58 +105,28 @@ export default { ...@@ -101,58 +105,28 @@ export default {
Objection.Model.knex(this.knex) Objection.Model.knex(this.knex)
// Load DB Models // Load DB Models
WIKI.logger.info('Loading DB models...') WIKI.logger.info('Loading DB models...')
const models = (await import(path.join(WIKI.SERVERPATH, 'models/index.mjs'))).default const models = (await import(path.join(WIKI.SERVERPATH, 'models/index.mjs'))).default
// Set init tasks // Connect
let conAttempts = 0 await this.connect()
const initTasks = {
// -> Attempt initial connection // Check DB Version
async connect () { const resVersion = await this.knex.raw('SHOW server_version;')
try { const dbVersion = semver.coerce(resVersion.rows[0].server_version, { loose: true })
WIKI.logger.info('Connecting to database...') this.VERSION = dbVersion.version
await self.knex.raw('SELECT 1 + 1;') this.LEGACY = dbVersion.major < 16
WIKI.logger.info('Database Connection Successful [ OK ]') if (dbVersion.major < 11) {
} catch (err) { WIKI.logger.error('Your PostgreSQL database version is too old and unsupported by Wiki.js. Exiting...')
if (conAttempts < 10) { process.exit(1)
if (err.code) {
WIKI.logger.error(`Database Connection Error: ${err.code} ${err.address}:${err.port}`)
} else {
WIKI.logger.error(`Database Connection Error: ${err.message}`)
}
WIKI.logger.warn(`Will retry in 3 seconds... [Attempt ${++conAttempts} of 10]`)
await setTimeout(3000)
await initTasks.connect()
} else {
throw err
}
}
},
// -> Migrate DB Schemas
async syncSchemas () {
WIKI.logger.info('Ensuring DB schema exists...')
await self.knex.raw(`CREATE SCHEMA IF NOT EXISTS ${WIKI.config.db.schemas.wiki}`)
WIKI.logger.info('Ensuring DB migrations have been applied...')
return self.knex.migrate.latest({
tableName: 'migrations',
migrationSource,
schemaName: WIKI.config.db.schemas.wiki
})
},
// -> Migrate DB Schemas from 2.x
async migrateFromLegacy () {
// return migrateFromLegacy.migrate(self.knex)
}
} }
WIKI.logger.info(`PostgreSQL ${dbVersion.version} [ ${this.LEGACY ? 'LEGACY MODE' : 'OK'} ]`)
// Perform init tasks // Run Migrations
if (!workerMode) {
this.onReady = workerMode ? Promise.resolve() : (async () => { await this.migrateFromLegacy()
await initTasks.connect() await this.syncSchemas()
await initTasks.migrateFromLegacy() }
await initTasks.syncSchemas()
})()
return { return {
...this, ...this,
...@@ -220,5 +194,47 @@ export default { ...@@ -220,5 +194,47 @@ export default {
event, event,
value value
}) })
},
/**
* Attempt initial connection
*/
async connect () {
try {
WIKI.logger.info('Connecting to database...')
await this.knex.raw('SELECT 1 + 1;')
WIKI.logger.info('Database Connection Successful [ OK ]')
} catch (err) {
if (this.connectAttempts < 10) {
if (err.code) {
WIKI.logger.error(`Database Connection Error: ${err.code} ${err.address}:${err.port}`)
} else {
WIKI.logger.error(`Database Connection Error: ${err.message}`)
}
WIKI.logger.warn(`Will retry in 3 seconds... [Attempt ${++this.connectAttempts} of 10]`)
await setTimeout(3000)
await this.connect()
} else {
throw err
}
}
},
/**
* Migrate DB Schemas
*/
async syncSchemas () {
WIKI.logger.info('Ensuring DB schema exists...')
await this.knex.raw(`CREATE SCHEMA IF NOT EXISTS ${WIKI.config.db.schemas.wiki}`)
WIKI.logger.info('Ensuring DB migrations have been applied...')
return this.knex.migrate.latest({
tableName: 'migrations',
migrationSource,
schemaName: WIKI.config.db.schemas.wiki
})
},
/**
* Migrate DB Schemas from 2.x
*/
async migrateFromLegacy () {
// return migrateFromLegacy.migrate(self.knex)
} }
} }
...@@ -21,7 +21,6 @@ export default { ...@@ -21,7 +21,6 @@ export default {
WIKI.db = await db.init() WIKI.db = await db.init()
try { try {
await WIKI.db.onReady
await WIKI.configSvc.loadFromDb() await WIKI.configSvc.loadFromDb()
await WIKI.configSvc.applyFlags() await WIKI.configSvc.applyFlags()
} catch (err) { } catch (err) {
......
...@@ -202,7 +202,7 @@ export default { ...@@ -202,7 +202,7 @@ export default {
return WIKI.config.db.host return WIKI.config.db.host
}, },
dbVersion () { dbVersion () {
return _.get(WIKI.db, 'knex.client.version', 'Unknown Version') return WIKI.db.VERSION
}, },
hostname () { hostname () {
return os.hostname() return os.hostname()
......
import _ from 'lodash-es' import _ from 'lodash-es'
import {
decodeFolderPath,
encodeFolderPath,
decodeTreePath,
encodeTreePath
} from '../../helpers/common.mjs'
import { generateError, generateSuccess } from '../../helpers/graph.mjs' import { generateError, generateSuccess } from '../../helpers/graph.mjs'
const typeResolvers = { const typeResolvers = {
...@@ -44,12 +50,12 @@ export default { ...@@ -44,12 +50,12 @@ export default {
if (args.parentId) { if (args.parentId) {
const parent = await WIKI.db.knex('tree').where('id', args.parentId).first() const parent = await WIKI.db.knex('tree').where('id', args.parentId).first()
if (parent) { if (parent) {
parentPath = (parent.folderPath ? `${parent.folderPath}.${parent.fileName}` : parent.fileName).replaceAll('-', '_') parentPath = (parent.folderPath ? `${decodeFolderPath(parent.folderPath)}.${parent.fileName}` : parent.fileName)
} }
} else if (args.parentPath) { } else if (args.parentPath) {
parentPath = args.parentPath.replaceAll('/', '.').replaceAll('-', '_').toLowerCase() parentPath = encodeTreePath(args.parentPath)
} }
const folderPathCondition = parentPath ? `${parentPath}.${depthCondition}` : depthCondition const folderPathCondition = parentPath ? `${encodeFolderPath(parentPath)}.${depthCondition}` : depthCondition
// Fetch Items // Fetch Items
const items = await WIKI.db.knex('tree') const items = await WIKI.db.knex('tree')
...@@ -59,9 +65,14 @@ export default { ...@@ -59,9 +65,14 @@ export default {
// -> Include ancestors // -> Include ancestors
if (args.includeAncestors) { if (args.includeAncestors) {
const parentPathParts = parentPath.split('.') const parentPathParts = parentPath.split('.')
for (let i = 1; i <= parentPathParts.length; i++) { for (let i = 0; i <= parentPathParts.length; i++) {
console.info({
folderPath: encodeFolderPath(_.dropRight(parentPathParts, i).join('.')),
fileName: _.nth(parentPathParts, i * -1),
type: 'folder'
})
builder.orWhere({ builder.orWhere({
folderPath: _.dropRight(parentPathParts, i).join('.'), folderPath: encodeFolderPath(_.dropRight(parentPathParts, i).join('.')),
fileName: _.nth(parentPathParts, i * -1), fileName: _.nth(parentPathParts, i * -1),
type: 'folder' type: 'folder'
}) })
...@@ -92,14 +103,14 @@ export default { ...@@ -92,14 +103,14 @@ export default {
id: item.id, id: item.id,
depth: item.depth, depth: item.depth,
type: item.type, type: item.type,
folderPath: item.folderPath.replaceAll('.', '/').replaceAll('_', '-'), folderPath: decodeTreePath(decodeFolderPath(item.folderPath)),
fileName: item.fileName, fileName: item.fileName,
title: item.title, title: item.title,
createdAt: item.createdAt, createdAt: item.createdAt,
updatedAt: item.updatedAt, updatedAt: item.updatedAt,
...(item.type === 'folder') && { ...(item.type === 'folder') && {
childrenCount: item.meta?.children || 0, childrenCount: item.meta?.children || 0,
isAncestor: item.folderPath.length < parentPath.length isAncestor: item.folderPath.length < parentPath.length || (parentPath !== '' && item.folderPath === parentPath)
}, },
...(item.type === 'asset') && { ...(item.type === 'asset') && {
fileSize: item.meta?.fileSize || 0, fileSize: item.meta?.fileSize || 0,
......
...@@ -37,7 +37,7 @@ export function createDeferred () { ...@@ -37,7 +37,7 @@ export function createDeferred () {
* @returns Decoded tree path * @returns Decoded tree path
*/ */
export function decodeTreePath (str) { export function decodeTreePath (str) {
return str.replaceAll('_', '-').replaceAll('.', '/') return str?.replaceAll('.', '/')
} }
/** /**
...@@ -47,7 +47,27 @@ export function decodeTreePath (str) { ...@@ -47,7 +47,27 @@ export function decodeTreePath (str) {
* @returns Encoded tree path * @returns Encoded tree path
*/ */
export function encodeTreePath (str) { export function encodeTreePath (str) {
return str?.toLowerCase()?.replaceAll('-', '_')?.replaceAll('/', '.') || '' return str?.toLowerCase()?.replaceAll('/', '.') || ''
}
/**
* Encode a folder path (to support legacy PostgresSQL ltree)
*
* @param {string} val String to encode
* @returns Encoded folder path
*/
export function encodeFolderPath (val) {
return WIKI.db.LEGACY ? val?.replaceAll('-', '_') : val
}
/**
* Decode a folder path (to support legacy PostgresSQL ltree)
*
* @param {string} val String to decode
* @returns Decoded folder path
*/
export function decodeFolderPath (val) {
return WIKI.db.LEGACY ? val?.replaceAll('_', '-') : val
} }
/** /**
......
import { Model } from 'objection' import { Model } from 'objection'
import { differenceWith, dropRight, last, nth } from 'lodash-es' import { differenceWith, dropRight, last, nth } from 'lodash-es'
import { decodeTreePath, encodeTreePath, generateHash } from '../helpers/common.mjs' import {
decodeFolderPath,
decodeTreePath,
encodeFolderPath,
encodeTreePath,
generateHash
} from '../helpers/common.mjs'
import { Locale } from './locales.mjs' import { Locale } from './locales.mjs'
import { Site } from './sites.mjs' import { Site } from './sites.mjs'
...@@ -87,7 +93,7 @@ export class Tree extends Model { ...@@ -87,7 +93,7 @@ export class Tree extends Model {
const parentPath = encodeTreePath(path) const parentPath = encodeTreePath(path)
const parentPathParts = parentPath.split('.') const parentPathParts = parentPath.split('.')
const parentFilter = { const parentFilter = {
folderPath: dropRight(parentPathParts).join('.'), folderPath: encodeFolderPath(dropRight(parentPathParts).join('.')),
fileName: last(parentPathParts) fileName: last(parentPathParts)
} }
const parent = await WIKI.db.knex('tree').where({ const parent = await WIKI.db.knex('tree').where({
...@@ -135,14 +141,14 @@ export class Tree extends Model { ...@@ -135,14 +141,14 @@ export class Tree extends Model {
folderPath: '', folderPath: '',
fileName: '' fileName: ''
} }
const folderPath = decodeTreePath(folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName) const folderPath = folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName
const fullPath = folderPath ? `${folderPath}/${fileName}` : fileName const fullPath = folderPath ? `${folderPath}/${fileName}` : fileName
WIKI.logger.debug(`Adding page ${fullPath} to tree...`) WIKI.logger.debug(`Adding page ${fullPath} to tree...`)
const pageEntry = await WIKI.db.knex('tree').insert({ const pageEntry = await WIKI.db.knex('tree').insert({
id, id,
folderPath, folderPath: encodeFolderPath(folderPath),
fileName, fileName,
type: 'page', type: 'page',
title: title, title: title,
...@@ -179,14 +185,13 @@ export class Tree extends Model { ...@@ -179,14 +185,13 @@ export class Tree extends Model {
fileName: '' fileName: ''
} }
const folderPath = folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName const folderPath = folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName
const decodedFolderPath = decodeTreePath(folderPath) const fullPath = folderPath ? `${folderPath}/${fileName}` : fileName
const fullPath = decodedFolderPath ? `${decodedFolderPath}/${fileName}` : fileName
WIKI.logger.debug(`Adding asset ${fullPath} to tree...`) WIKI.logger.debug(`Adding asset ${fullPath} to tree...`)
const assetEntry = await WIKI.db.knex('tree').insert({ const assetEntry = await WIKI.db.knex('tree').insert({
id, id,
folderPath, folderPath: encodeFolderPath(folderPath),
fileName, fileName,
type: 'asset', type: 'asset',
title: title, title: title,
...@@ -225,7 +230,7 @@ export class Tree extends Model { ...@@ -225,7 +230,7 @@ export class Tree extends Model {
WIKI.logger.debug(`Creating new folder ${pathName}...`) WIKI.logger.debug(`Creating new folder ${pathName}...`)
const parentPathParts = parentPath.split('.') const parentPathParts = parentPath.split('.')
const parentFilter = { const parentFilter = {
folderPath: dropRight(parentPathParts).join('.'), folderPath: encodeFolderPath(dropRight(parentPathParts).join('.')),
fileName: last(parentPathParts) fileName: last(parentPathParts)
} }
...@@ -236,7 +241,7 @@ export class Tree extends Model { ...@@ -236,7 +241,7 @@ export class Tree extends Model {
if (!parent) { if (!parent) {
throw new Error('ERR_NONEXISTING_PARENT_ID') throw new Error('ERR_NONEXISTING_PARENT_ID')
} }
parentPath = parent.folderPath ? `${parent.folderPath}.${parent.fileName}` : parent.fileName parentPath = parent.folderPath ? `${decodeFolderPath(parent.folderPath)}.${parent.fileName}` : parent.fileName
} else if (parentPath) { } else if (parentPath) {
parent = await WIKI.db.knex('tree').where(parentFilter).first() parent = await WIKI.db.knex('tree').where(parentFilter).first()
} else { } else {
...@@ -247,7 +252,7 @@ export class Tree extends Model { ...@@ -247,7 +252,7 @@ export class Tree extends Model {
const existingFolder = await WIKI.db.knex('tree').select('id').where({ const existingFolder = await WIKI.db.knex('tree').select('id').where({
siteId: siteId, siteId: siteId,
localeCode: locale, localeCode: locale,
folderPath: encodeTreePath(parentPath), folderPath: encodeFolderPath(parentPath),
fileName: pathName fileName: pathName
}).first() }).first()
if (existingFolder) { if (existingFolder) {
...@@ -261,7 +266,7 @@ export class Tree extends Model { ...@@ -261,7 +266,7 @@ export class Tree extends Model {
const parentPathParts = parentPath.split('.') const parentPathParts = parentPath.split('.')
for (let i = 1; i <= parentPathParts.length; i++) { for (let i = 1; i <= parentPathParts.length; i++) {
const ancestor = { const ancestor = {
folderPath: encodeTreePath(dropRight(parentPathParts, i).join('.')), folderPath: encodeFolderPath(dropRight(parentPathParts, i).join('.')),
fileName: nth(parentPathParts, i * -1) fileName: nth(parentPathParts, i * -1)
} }
expectedAncestors.push(ancestor) expectedAncestors.push(ancestor)
...@@ -296,7 +301,7 @@ export class Tree extends Model { ...@@ -296,7 +301,7 @@ export class Tree extends Model {
// Create folder // Create folder
const fullPath = parentPath ? `${decodeTreePath(parentPath)}/${pathName}` : pathName const fullPath = parentPath ? `${decodeTreePath(parentPath)}/${pathName}` : pathName
const folder = await WIKI.db.knex('tree').insert({ const folder = await WIKI.db.knex('tree').insert({
folderPath: encodeTreePath(parentPath), folderPath: encodeFolderPath(parentPath),
fileName: pathName, fileName: pathName,
type: 'folder', type: 'folder',
title: title, title: title,
...@@ -364,8 +369,8 @@ export class Tree extends Model { ...@@ -364,8 +369,8 @@ export class Tree extends Model {
} }
// Build new paths // Build new paths
const oldFolderPath = (folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName).replaceAll('-', '_') const oldFolderPath = encodeFolderPath(folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName)
const newFolderPath = (folder.folderPath ? `${folder.folderPath}.${pathName}` : pathName).replaceAll('-', '_') const newFolderPath = encodeFolderPath(folder.folderPath ? `${folder.folderPath}.${pathName}` : pathName)
// Update children nodes // Update children nodes
WIKI.logger.debug(`Updating parent path of children nodes from ${oldFolderPath} to ${newFolderPath} ...`) WIKI.logger.debug(`Updating parent path of children nodes from ${oldFolderPath} to ${newFolderPath} ...`)
...@@ -377,7 +382,7 @@ export class Tree extends Model { ...@@ -377,7 +382,7 @@ export class Tree extends Model {
}) })
// Rename the folder itself // Rename the folder itself
const fullPath = folder.folderPath ? `${decodeTreePath(folder.folderPath)}/${pathName}` : pathName const fullPath = folder.folderPath ? `${decodeFolderPath(folder.folderPath)}/${pathName}` : pathName
await WIKI.db.knex('tree').where('id', folder.id).update({ await WIKI.db.knex('tree').where('id', folder.id).update({
fileName: pathName, fileName: pathName,
title: title, title: title,
...@@ -408,7 +413,7 @@ export class Tree extends Model { ...@@ -408,7 +413,7 @@ export class Tree extends Model {
WIKI.logger.debug(`Deleting folder ${folder.id} at path ${folderPath}...`) WIKI.logger.debug(`Deleting folder ${folder.id} at path ${folderPath}...`)
// Delete all children // Delete all children
const deletedNodes = await WIKI.db.knex('tree').where('folderPath', '<@', folderPath).del().returning(['id', 'type']) const deletedNodes = await WIKI.db.knex('tree').where('folderPath', '<@', encodeFolderPath(folderPath)).del().returning(['id', 'type'])
// Delete folders // Delete folders
const deletedFolders = deletedNodes.filter(n => n.type === 'folder').map(n => n.id) const deletedFolders = deletedNodes.filter(n => n.type === 'folder').map(n => n.id)
...@@ -439,7 +444,7 @@ export class Tree extends Model { ...@@ -439,7 +444,7 @@ export class Tree extends Model {
if (folder.folderPath) { if (folder.folderPath) {
const parentPathParts = folder.folderPath.split('.') const parentPathParts = folder.folderPath.split('.')
const parent = await WIKI.db.knex('tree').where({ const parent = await WIKI.db.knex('tree').where({
folderPath: dropRight(parentPathParts).join('.'), folderPath: encodeFolderPath(dropRight(parentPathParts).join('.')),
fileName: last(parentPathParts) fileName: last(parentPathParts)
}).first() }).first()
await WIKI.db.knex('tree').where('id', parent.id).update({ await WIKI.db.knex('tree').where('id', parent.id).update({
......
...@@ -34,18 +34,18 @@ ...@@ -34,18 +34,18 @@
"node": ">=18.0" "node": ">=18.0"
}, },
"dependencies": { "dependencies": {
"@apollo/server": "4.7.1", "@apollo/server": "4.7.3",
"@azure/storage-blob": "12.14.0", "@azure/storage-blob": "12.14.0",
"@exlinc/keycloak-passport": "1.0.2", "@exlinc/keycloak-passport": "1.0.2",
"@graphql-tools/schema": "10.0.0", "@graphql-tools/schema": "10.0.0",
"@graphql-tools/utils": "10.0.0", "@graphql-tools/utils": "10.0.1",
"@joplin/turndown-plugin-gfm": "1.0.47", "@joplin/turndown-plugin-gfm": "1.0.47",
"@root/csr": "0.8.1", "@root/csr": "0.8.1",
"@root/keypairs": "0.10.3", "@root/keypairs": "0.10.3",
"@root/pem": "1.0.4", "@root/pem": "1.0.4",
"acme": "3.0.3", "acme": "3.0.3",
"akismet-api": "6.0.0", "akismet-api": "6.0.0",
"aws-sdk": "2.1386.0", "aws-sdk": "2.1395.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.20.2", "body-parser": "1.20.2",
"chalk": "5.2.0", "chalk": "5.2.0",
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
"express": "4.18.2", "express": "4.18.2",
"express-brute": "1.0.1", "express-brute": "1.0.1",
"express-session": "1.17.3", "express-session": "1.17.3",
"file-type": "18.4.0", "file-type": "18.5.0",
"filesize": "10.0.7", "filesize": "10.0.7",
"fs-extra": "11.1.1", "fs-extra": "11.1.1",
"getos": "3.2.1", "getos": "3.2.1",
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
"graphql-upload": "16.0.2", "graphql-upload": "16.0.2",
"he": "1.2.0", "he": "1.2.0",
"highlight.js": "11.8.0", "highlight.js": "11.8.0",
"i18next": "22.5.0", "i18next": "22.5.1",
"i18next-node-fs-backend": "2.1.3", "i18next-node-fs-backend": "2.1.3",
"image-size": "1.0.2", "image-size": "1.0.2",
"js-base64": "3.7.5", "js-base64": "3.7.5",
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
"nanoid": "4.0.2", "nanoid": "4.0.2",
"node-2fa": "2.0.3", "node-2fa": "2.0.3",
"node-cache": "5.1.2", "node-cache": "5.1.2",
"nodemailer": "6.9.2", "nodemailer": "6.9.3",
"objection": "3.0.1", "objection": "3.0.1",
"passport": "0.6.0", "passport": "0.6.0",
"passport-auth0": "1.4.3", "passport-auth0": "1.4.3",
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
"passport-okta-oauth": "0.0.1", "passport-okta-oauth": "0.0.1",
"passport-openidconnect": "0.1.1", "passport-openidconnect": "0.1.1",
"passport-saml": "3.2.1", "passport-saml": "3.2.1",
"passport-slack-oauth2": "1.1.1", "passport-slack-oauth2": "1.2.0",
"passport-twitch-strategy": "2.2.0", "passport-twitch-strategy": "2.2.0",
"pem-jwk": "2.0.0", "pem-jwk": "2.0.0",
"pg": "8.11.0", "pg": "8.11.0",
...@@ -144,9 +144,9 @@ ...@@ -144,9 +144,9 @@
"pg-pubsub": "0.8.1", "pg-pubsub": "0.8.1",
"pg-query-stream": "4.5.0", "pg-query-stream": "4.5.0",
"pg-tsquery": "8.4.1", "pg-tsquery": "8.4.1",
"poolifier": "2.4.14", "poolifier": "2.6.2",
"punycode": "2.3.0", "punycode": "2.3.0",
"puppeteer-core": "20.4.0", "puppeteer-core": "20.5.0",
"qr-image": "3.2.0", "qr-image": "3.2.0",
"rate-limiter-flexible": "2.4.1", "rate-limiter-flexible": "2.4.1",
"remove-markdown": "0.5.0", "remove-markdown": "0.5.0",
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
"serve-favicon": "2.5.0", "serve-favicon": "2.5.0",
"sharp": "0.32.1", "sharp": "0.32.1",
"simple-git": "3.19.0", "simple-git": "3.19.0",
"socket.io": "4.6.1", "socket.io": "4.6.2",
"striptags": "3.2.0", "striptags": "3.2.0",
"tar-fs": "2.1.1", "tar-fs": "2.1.1",
"turndown": "7.1.2", "turndown": "7.1.2",
...@@ -171,9 +171,9 @@ ...@@ -171,9 +171,9 @@
"yargs": "17.7.2" "yargs": "17.7.2"
}, },
"devDependencies": { "devDependencies": {
"eslint": "8.41.0", "eslint": "8.42.0",
"eslint-config-requarks": "1.0.7", "eslint-config-requarks": "1.0.7",
"eslint-config-standard": "17.0.0", "eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.27.5", "eslint-plugin-import": "2.27.5",
"eslint-plugin-node": "11.1.0", "eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "6.1.1", "eslint-plugin-promise": "6.1.1",
...@@ -181,7 +181,7 @@ ...@@ -181,7 +181,7 @@
"nodemon": "2.0.22" "nodemon": "2.0.22"
}, },
"overrides": { "overrides": {
"@graphql-tools/utils": "10.0.0" "@graphql-tools/utils": "10.0.1"
}, },
"collective": { "collective": {
"type": "opencollective", "type": "opencollective",
......
...@@ -10,11 +10,12 @@ export async function task (payload) { ...@@ -10,11 +10,12 @@ export async function task (payload) {
version: strictVersion, version: strictVersion,
versionDate: resp.published_at versionDate: resp.published_at
} }
await WIKI.config.saveToDb(['update']) await WIKI.configSvc.saveToDb(['update'])
WIKI.logger.info('Checked for latest version: [ COMPLETED ]') WIKI.logger.info('Checked for latest version: [ COMPLETED ]')
} catch (err) { } catch (err) {
WIKI.logger.error('Checking for latest version: [ FAILED ]') WIKI.logger.error('Checking for latest version: [ FAILED ]')
WIKI.logger.error(err.message) WIKI.logger.error(err.message)
throw err
} }
} }
...@@ -13,5 +13,6 @@ export async function task (payload) { ...@@ -13,5 +13,6 @@ export async function task (payload) {
} catch (err) { } catch (err) {
WIKI.logger.error('Cleaning scheduler job history: [ FAILED ]') WIKI.logger.error('Cleaning scheduler job history: [ FAILED ]')
WIKI.logger.error(err.message) WIKI.logger.error(err.message)
throw err
} }
} }
...@@ -48,5 +48,6 @@ export async function task (payload) { ...@@ -48,5 +48,6 @@ export async function task (payload) {
} catch (err) { } catch (err) {
WIKI.logger.error('Fetching latest localization data: [ FAILED ]') WIKI.logger.error('Fetching latest localization data: [ FAILED ]')
WIKI.logger.error(err.message) WIKI.logger.error(err.message)
throw err
} }
} }
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
"ncu-u": "ncu -u -x codemirror,codemirror-asciidoc" "ncu-u": "ncu -u -x codemirror,codemirror-asciidoc"
}, },
"dependencies": { "dependencies": {
"@apollo/client": "3.7.14", "@apollo/client": "3.7.15",
"@lezer/common": "1.0.2", "@lezer/common": "1.0.3",
"@mdi/font": "7.2.96", "@mdi/font": "7.2.96",
"@quasar/extras": "1.16.4", "@quasar/extras": "1.16.4",
"@tiptap/core": "2.0.3", "@tiptap/core": "2.0.3",
...@@ -74,21 +74,21 @@ ...@@ -74,21 +74,21 @@
"markdown-it-sup": "1.0.0", "markdown-it-sup": "1.0.0",
"markdown-it-task-lists": "2.1.1", "markdown-it-task-lists": "2.1.1",
"mitt": "3.0.0", "mitt": "3.0.0",
"monaco-editor": "0.38.0", "monaco-editor": "0.39.0",
"pako": "2.1.0", "pako": "2.1.0",
"pinia": "2.1.3", "pinia": "2.1.3",
"prosemirror-commands": "1.5.2", "prosemirror-commands": "1.5.2",
"prosemirror-history": "1.3.2", "prosemirror-history": "1.3.2",
"prosemirror-keymap": "1.2.2", "prosemirror-keymap": "1.2.2",
"prosemirror-model": "1.19.2", "prosemirror-model": "1.19.2",
"prosemirror-schema-list": "1.2.3", "prosemirror-schema-list": "1.3.0",
"prosemirror-state": "1.4.3", "prosemirror-state": "1.4.3",
"prosemirror-transform": "1.7.2", "prosemirror-transform": "1.7.3",
"prosemirror-view": "1.31.3", "prosemirror-view": "1.31.4",
"pug": "3.0.2", "pug": "3.0.2",
"quasar": "2.12.0", "quasar": "2.12.0",
"slugify": "1.6.6", "slugify": "1.6.6",
"socket.io-client": "4.6.1", "socket.io-client": "4.6.2",
"tabulator-tables": "5.5.0", "tabulator-tables": "5.5.0",
"tippy.js": "6.3.7", "tippy.js": "6.3.7",
"twemoji": "14.0.2", "twemoji": "14.0.2",
...@@ -96,10 +96,10 @@ ...@@ -96,10 +96,10 @@
"v-network-graph": "0.9.3", "v-network-graph": "0.9.3",
"vue": "3.3.4", "vue": "3.3.4",
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",
"vue-router": "4.2.1", "vue-router": "4.2.2",
"vue3-otp-input": "0.4.1", "vue3-otp-input": "0.4.1",
"vuedraggable": "4.1.0", "vuedraggable": "4.1.0",
"xterm": "5.1.0", "xterm": "5.2.1",
"zxcvbn": "4.4.2" "zxcvbn": "4.4.2"
}, },
"devDependencies": { "devDependencies": {
...@@ -109,10 +109,10 @@ ...@@ -109,10 +109,10 @@
"@volar/vue-language-plugin-pug": "1.6.5", "@volar/vue-language-plugin-pug": "1.6.5",
"autoprefixer": "10.4.14", "autoprefixer": "10.4.14",
"browserlist": "latest", "browserlist": "latest",
"eslint": "8.41.0", "eslint": "8.42.0",
"eslint-config-standard": "17.0.0", "eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.27.5", "eslint-plugin-import": "2.27.5",
"eslint-plugin-n": "15.7.0", "eslint-plugin-n": "16.0.0",
"eslint-plugin-promise": "6.1.1", "eslint-plugin-promise": "6.1.1",
"eslint-plugin-vue": "9.14.1" "eslint-plugin-vue": "9.14.1"
}, },
......
...@@ -615,7 +615,7 @@ async function loadTree ({ parentId = null, parentPath = null, types, initLoad = ...@@ -615,7 +615,7 @@ async function loadTree ({ parentId = null, parentPath = null, types, initLoad =
// -> Set Ancestors / Tree Roots // -> Set Ancestors / Tree Roots
if (item.folderPath) { if (item.folderPath) {
if (!state.treeNodes[parentId].children.includes(item.id)) { if (item.id !== parentId && !state.treeNodes[parentId].children.includes(item.id)) {
state.treeNodes[parentId].children.push(item.id) state.treeNodes[parentId].children.push(item.id)
} }
} else { } else {
...@@ -725,9 +725,20 @@ function renameFolder (folderId) { ...@@ -725,9 +725,20 @@ function renameFolder (folderId) {
componentProps: { componentProps: {
folderId folderId
} }
}).onOk(() => { }).onOk(async () => {
treeComp.value.resetLoaded() treeComp.value.resetLoaded()
loadTree({ parentId: folderId, initLoad: true }) // // -> Delete current folder and children from cache
// const fPath = [state.treeNodes[folderId].folderPath, state.treeNodes[folderId].fileName].filter(p => !!p).join('/')
// delete state.treeNodes[folderId]
// for (const [nodeId, node] of Object.entries(state.treeNodes)) {
// if (node.folderPath.startsWith(fPath)) {
// delete state.treeNodes[nodeId]
// }
// }
// -> Reload tree
await loadTree({ parentId: folderId, types: ['folder'], initLoad: true }) // Update tree
// -> Reload current view (in case current folder is included)
await loadTree({ parentId: state.currentFolderId })
}) })
} }
......
...@@ -204,6 +204,7 @@ onMounted(async () => { ...@@ -204,6 +204,7 @@ onMounted(async () => {
} }
} }
`, `,
fetchPolicy: 'network-only',
variables: { variables: {
id: props.folderId id: props.folderId
} }
......
<template lang="pug"> <template lang="pug">
q-menu.translucent-menu( q-menu.translucent-menu(
auto-close auto-close
anchor='top right' anchor='bottom middle'
self='top left' self='top left'
) )
q-list(padding, style='min-width: 200px;') q-list(padding, style='min-width: 200px;')
......
...@@ -249,6 +249,11 @@ ...@@ -249,6 +249,11 @@
border-color: $green-5; border-color: $green-5;
} }
} }
.codeblock > code {
background-color: inherit;
color: inherit;
}
} }
// --------------------------------- // ---------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment