diff --git a/package.json b/package.json index 3673137ff..34cefe7fd 100755 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "defu": "^5.0.0", "detab": "^3.0.0", "directory-tree": "^2.2.9", + "fast-glob": "^3.2.6", "flat": "^5.0.2", "graceful-fs": "^4.2.6", "gray-matter": "^4.0.3", @@ -90,7 +91,7 @@ "nuxt-extend": "^0.1.0", "nuxt-i18n": "^6.27.2", "nuxt-vite": "^0.1.1", - "nuxt-windicss": "1.1.3", + "nuxt-windicss": "^1.1.3", "ohmyfetch": "^0.1.8", "plausible-tracker": "^0.3.1", "prism-theme-vars": "^0.2.2", @@ -121,7 +122,8 @@ "vue-docgen-api": "^4.40.0", "vue-plausible": "^1.1.4", "vue3": "npm:vue@next", - "vue3-router": "npm:vue-router@next" + "vue3-router": "npm:vue-router@next", + "windicss-analysis": "^0.3.4" }, "devDependencies": { "@iconify/json": "^1.1.372", diff --git a/src/admin/api/functions/components.ts b/src/admin/api/functions/components.ts new file mode 100644 index 000000000..29fd4dce2 --- /dev/null +++ b/src/admin/api/functions/components.ts @@ -0,0 +1,65 @@ +import { promises as fs } from 'fs' +import { join, extname } from 'path' +import { createError, Middleware, useBody } from 'h3' +import dirTree from 'directory-tree' +import { FileData, File } from '../../type' +import { normalizeFiles, r } from '../utils' + +export default async function componentsHandler(req) { + const url = req.url + + if (req.method === 'GET') { + // List all files in components/ + if (url === '/') { + const tree = dirTree(r('components')) + return normalizeFiles(tree.children, r('components')) + } + // Read a single content file + try { + const path = join(r('components'), url) + const file = await fs.readFile(path, 'utf-8') + + return { + path: path.replace(r('components'), ''), + extension: extname(path), + raw: file + } + } catch (err) { + return createError({ + statusCode: 404, + statusMessage: 'File not found' + }) + } + } + + // Update changes + if (req.method === 'PUT') { + const { raw } = await useBody(req) + if (raw == null) { + return createError({ + statusCode: 400, + statusMessage: '"raw" key is required' + }) + } + + const path = join(r('components'), url) + + try { + // @ts-ignore + // await fs.stat(path, 'utf-8') + await fs.writeFile(path, raw) + + return { ok: true } + } catch (err) { + return createError({ + statusCode: 404, + statusMessage: 'File not found' + }) + } + } + + return createError({ + statusCode: 400, + statusMessage: 'Bad Request' + }) +} diff --git a/src/admin/api/functions/config.ts b/src/admin/api/functions/config.ts new file mode 100644 index 000000000..1f3853aca --- /dev/null +++ b/src/admin/api/functions/config.ts @@ -0,0 +1,49 @@ +import { parse } from 'path' +import fs from 'fs-extra' +import { createError, Middleware, useBody } from 'h3' +import { FileData } from '../../type' +import { r } from '../utils' + +export default async function configHandler(req) { + const root = r() + let path = [r('nuxt.config.ts'), r('nuxt.config.js')].find(i => fs.existsSync(i)) + const exist = Boolean(path) + path = path || r('nuxt.config.ts') + + if (req.method === 'GET') { + // Get config file + return { + path: path.replace(root, ''), + exist, + extension: parse(path).ext, + raw: exist ? await fs.readFile(path, 'utf-8') : '' + } + } + + // Update config + if (req.method === 'PUT') { + const { raw } = await useBody(req) + if (raw == null) { + return createError({ + statusCode: 400, + statusMessage: '"raw" key is required' + }) + } + + try { + await fs.writeFile(path, raw) + + return { ok: true } + } catch (err) { + return createError({ + statusCode: 404, + statusMessage: 'File not found' + }) + } + } + + return createError({ + statusCode: 400, + statusMessage: 'Bad Request' + }) +} diff --git a/src/admin/api/index.ts b/src/admin/api/index.ts index 830173ecf..ea6defa51 100644 --- a/src/admin/api/index.ts +++ b/src/admin/api/index.ts @@ -2,11 +2,15 @@ import { createApp } from 'h3' import contentHandler from './functions/content' import previewHandler from './functions/preview' import staticHandler from './functions/static' +import componentsHandler from './functions/components' +import configHandler from './functions/config' const app = createApp() app.useAsync('/content', contentHandler) app.useAsync('/preview', previewHandler) app.useAsync('/static', staticHandler) +app.useAsync('/components', componentsHandler) +app.useAsync('/config', configHandler) export default app._handle diff --git a/src/admin/app/components/AppHeaderNav.vue b/src/admin/app/components/AppHeaderNav.vue index a63fd1c84..6b031b988 100644 --- a/src/admin/app/components/AppHeaderNav.vue +++ b/src/admin/app/components/AppHeaderNav.vue @@ -9,11 +9,35 @@ Static + + Components + + + + Config + + + + Windi Analyzer + +