123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- import _ from 'lodash-es'
- import {
- decodeFolderPath,
- encodeFolderPath,
- decodeTreePath,
- encodeTreePath
- } from '../../helpers/common.mjs'
- import { generateError, generateSuccess } from '../../helpers/graph.mjs'
- const typeResolvers = {
- folder: 'TreeItemFolder',
- page: 'TreeItemPage',
- asset: 'TreeItemAsset'
- }
- const rePathName = /^[a-z0-9-]+$/
- const reTitle = /^[^<>"]+$/
- export default {
- Query: {
- /**
- * FETCH TREE
- */
- async tree (obj, args, context, info) {
- // Offset
- const offset = args.offset || 0
- if (offset < 0) {
- throw new Error('Invalid Offset')
- }
- // Limit
- const limit = args.limit || 1000
- if (limit < 1 || limit > 1000) {
- throw new Error('Invalid Limit')
- }
- // Order By
- const orderByDirection = args.orderByDirection || 'asc'
- const orderBy = args.orderBy || 'title'
- // Parse depth
- const depth = args.depth || 0
- if (depth < 0 || depth > 10) {
- throw new Error('Invalid Depth')
- }
- const depthCondition = depth > 0 ? `*{,${depth}}` : '*{0}'
- // Get parent path
- let parentPath = ''
- if (args.parentId) {
- const parent = await WIKI.db.knex('tree').where('id', args.parentId).first()
- if (parent) {
- parentPath = (parent.folderPath ? `${decodeFolderPath(parent.folderPath)}.${parent.fileName}` : parent.fileName)
- }
- } else if (args.parentPath) {
- parentPath = encodeTreePath(args.parentPath)
- }
- const folderPathCondition = parentPath ? `${encodeFolderPath(parentPath)}.${depthCondition}` : depthCondition
- // Fetch Items
- const items = await WIKI.db.knex('tree')
- .select(WIKI.db.knex.raw('tree.*, nlevel(tree."folderPath") AS depth'))
- .where(builder => {
- builder.where('folderPath', '~', folderPathCondition)
- // -> Include ancestors
- if (args.includeAncestors) {
- const parentPathParts = parentPath.split('.')
- for (let i = 0; i <= parentPathParts.length; i++) {
- builder.orWhere({
- folderPath: encodeFolderPath(_.dropRight(parentPathParts, i).join('.')),
- fileName: _.nth(parentPathParts, i * -1),
- type: 'folder'
- })
- }
- }
- // -> Include root items
- if (args.includeRootFolders) {
- builder.orWhere({
- folderPath: '',
- type: 'folder'
- })
- }
- // -> Filter by tags
- if (args.tags && args.tags.length > 0) {
- builder.where('tags', '@>', args.tags)
- }
- })
- .andWhere(builder => {
- // -> Limit to specific types
- if (args.types && args.types.length > 0) {
- builder.whereIn('type', args.types)
- }
- })
- .limit(limit)
- .offset(offset)
- .orderBy([
- { column: 'depth' },
- { column: orderBy, order: orderByDirection }
- ])
- return items.map(item => ({
- id: item.id,
- depth: item.depth,
- type: item.type,
- folderPath: decodeTreePath(decodeFolderPath(item.folderPath)),
- fileName: item.fileName,
- title: item.title,
- tags: item.tags ?? [],
- createdAt: item.createdAt,
- updatedAt: item.updatedAt,
- ...(item.type === 'folder') && {
- childrenCount: item.meta?.children || 0,
- isAncestor: item.folderPath.length < parentPath.length
- },
- ...(item.type === 'asset') && {
- fileSize: item.meta?.fileSize || 0,
- fileExt: item.meta?.fileExt || '',
- mimeType: item.meta?.mimeType || ''
- },
- ...(item.type === 'page') && {
- description: item.meta?.description || ''
- }
- }))
- },
- /**
- * FETCH SINGLE FOLDER BY ID
- */
- async folderById (obj, args, context) {
- const folder = await WIKI.db.knex('tree')
- .select(WIKI.db.knex.raw('tree.*, nlevel(tree."folderPath") AS depth'))
- .where('id', args.id)
- .first()
- if (!folder) {
- throw new Error('ERR_INVALID_FOLDER')
- }
- return {
- ...folder,
- folderPath: folder.folderPath.replaceAll('.', '/').replaceAll('_', '-'),
- childrenCount: folder.meta?.children || 0
- }
- },
- /**
- * FETCH SINGLE FOLDER BY PATH
- */
- async folderByPath (obj, args, context) {
- const parentPathParts = args.path.replaceAll('/', '.').replaceAll('-', '_').split('.')
- const folder = await WIKI.db.knex('tree')
- .select(WIKI.db.knex.raw('tree.*, nlevel(tree."folderPath") AS depth'))
- .where({
- siteId: args.siteId,
- locale: args.locale,
- folderPath: _.dropRight(parentPathParts).join('.'),
- fileName: _.last(parentPathParts)
- })
- .first()
- if (!folder) {
- throw new Error('ERR_INVALID_FOLDER')
- }
- return {
- ...folder,
- folderPath: folder.folderPath.replaceAll('.', '/').replaceAll('_', '-'),
- childrenCount: folder.meta?.children || 0
- }
- }
- },
- Mutation: {
- /**
- * CREATE FOLDER
- */
- async createFolder (obj, args, context) {
- try {
- await WIKI.db.tree.createFolder(args)
- return {
- operation: generateSuccess('Folder created successfully')
- }
- } catch (err) {
- WIKI.logger.debug(`Failed to create folder: ${err.message}`)
- return generateError(err)
- }
- },
- /**
- * RENAME FOLDER
- */
- async renameFolder (obj, args, context) {
- try {
- await WIKI.db.tree.renameFolder(args)
- return {
- operation: generateSuccess('Folder renamed successfully')
- }
- } catch (err) {
- WIKI.logger.debug(`Failed to rename folder ${args.folderId}: ${err.message}`)
- return generateError(err)
- }
- },
- /**
- * DELETE FOLDER
- */
- async deleteFolder (obj, args, context) {
- try {
- await WIKI.db.tree.deleteFolder(args.folderId)
- return {
- operation: generateSuccess('Folder deleted successfully')
- }
- } catch (err) {
- WIKI.logger.debug(`Failed to delete folder ${args.folderId}: ${err.message}`)
- return generateError(err)
- }
- }
- },
- TreeItem: {
- __resolveType (obj, context, info) {
- return typeResolvers[obj.type] ?? null
- }
- }
- }
|