From 79470726280c6ffe9ba204fa8077c812366d2954 Mon Sep 17 00:00:00 2001 From: terwer Date: Mon, 29 Aug 2022 09:49:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:#1=20=E4=BF=AE=E5=A4=8D=E6=8B=BC=E5=86=99?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- lib/api.ts | 54 ++++++++ lib/common/post.ts | 39 ++++++ lib/common/siteconfig.ts | 26 ++++ lib/common/userBlog.ts | 14 ++ lib/constants.ts | 11 ++ lib/constants/metaweblogMethodConstants.ts | 15 +++ lib/constants/postStatusConstants.ts | 9 ++ lib/constants/serverApiConstants.ts | 7 + lib/htmlUtil.ts | 127 +++++++++++++++++ lib/logUtil.ts | 63 +++++++++ lib/markdownUtil.ts | 11 ++ lib/siyuan/siYuanApi.ts | 150 +++++++++++++++++++++ lib/siyuan/siYuanApiAdaptor.ts | 129 ++++++++++++++++++ package.json | 4 + pages/index.vue | 32 +++++ pages/post.vue | 23 ++++ server/api/endpoint/getPost.ts | 20 +++ server/api/endpoint/getRecentPosts.ts | 22 +++ server/api/hello.ts | 7 + server/middleware/log.ts | 3 + yarn.lock | 17 +++ 22 files changed, 784 insertions(+), 1 deletion(-) create mode 100644 lib/api.ts create mode 100644 lib/common/post.ts create mode 100644 lib/common/siteconfig.ts create mode 100644 lib/common/userBlog.ts create mode 100644 lib/constants.ts create mode 100644 lib/constants/metaweblogMethodConstants.ts create mode 100644 lib/constants/postStatusConstants.ts create mode 100644 lib/constants/serverApiConstants.ts create mode 100644 lib/htmlUtil.ts create mode 100644 lib/logUtil.ts create mode 100644 lib/markdownUtil.ts create mode 100644 lib/siyuan/siYuanApi.ts create mode 100644 lib/siyuan/siYuanApiAdaptor.ts create mode 100644 pages/index.vue create mode 100644 pages/post.vue create mode 100644 server/api/endpoint/getPost.ts create mode 100644 server/api/endpoint/getRecentPosts.ts create mode 100644 server/api/hello.ts create mode 100644 server/middleware/log.ts diff --git a/README.md b/README.md index 5f598e4..b25bfad 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # jvue-front Next version for jvue-front using [nuxt3](https://github.com/nuxt/framework) which supports Metaweblog API. -We will start develop after Nuxt3 **stabe*** release,please wait... +We will start develop after Nuxt3 **stabe** release,please wait... ## build diff --git a/lib/api.ts b/lib/api.ts new file mode 100644 index 0000000..ea3fed2 --- /dev/null +++ b/lib/api.ts @@ -0,0 +1,54 @@ +import {SiYuanApiAdaptor} from "~/lib/siyuan/siYuanApiAdaptor"; +import {API_TYPE_CONSTANTS} from "~/lib/constants"; +import {Post} from "~/lib/common/post"; +import {UserBlog} from "~/lib/common/userBlog"; + +export interface IApi { + /** + * 博客配置列表 + */ + getUsersBlogs(): Promise> + + /** + * 最新文章 + * @param numOfPosts 文章数目 + * @param page 页码(可选,部分平台不支持分页) + * @param keyword 关键字(可选,部分平台不支持搜索) + */ + getRecentPosts(numOfPosts: number, page?: number, keyword?: string): Promise> + + /** + * 文章详情 + * @param postid + * @param useSlug 是否使用的是别名(可选,部分平台不支持) + */ + getPost(postid: string, useSlug?: boolean): Promise +} + +export class API implements IApi { + type: string + private apiAdaptor: IApi + + constructor(type: string, env: any) { + this.type = type; + switch (this.type) { + case API_TYPE_CONSTANTS.API_TYPE_SIYUAN: + this.apiAdaptor = new SiYuanApiAdaptor(env) + break; + default: + throw new Error("未找到接口适配器,请检查参数") + } + } + + async getRecentPosts(numOfPosts: number, page?: number, keyword?: string): Promise> { + return this.apiAdaptor.getRecentPosts(numOfPosts, page, keyword); + } + + async getUsersBlogs(): Promise> { + return this.apiAdaptor.getUsersBlogs(); + } + + getPost(postid: string, useSlug?: boolean): Promise { + return this.apiAdaptor.getPost(postid, useSlug); + } +} \ No newline at end of file diff --git a/lib/common/post.ts b/lib/common/post.ts new file mode 100644 index 0000000..afd012c --- /dev/null +++ b/lib/common/post.ts @@ -0,0 +1,39 @@ +/** + * 通用文章模型定义 + */ +import {POST_STATUS_CONSTANTS} from "~/lib/constants/postStatusConstants"; + +export class Post { + postid: string + title: string + /** + * 逗号分隔的标签 + */ + mt_keywords: string + link?: string + permalink: string + shortDesc?:string + description: string + mt_excerpt?: string + wp_slug: string + dateCreated: Date + categories: Array + mt_text_more?: string + post_status?:string + isPublished: boolean + wp_password: string + + constructor() { + this.postid = "" + this.title = "" + this.mt_keywords = "" + this.permalink = "" + this.description = "" + this.wp_slug = "" + this.dateCreated = new Date() + this.categories = [] + this.isPublished = true + this.post_status = POST_STATUS_CONSTANTS.POST_STATUS_PUBLISH + this.wp_password = "" + } +} \ No newline at end of file diff --git a/lib/common/siteconfig.ts b/lib/common/siteconfig.ts new file mode 100644 index 0000000..15d374e --- /dev/null +++ b/lib/common/siteconfig.ts @@ -0,0 +1,26 @@ +import {UserBlog} from "./userBlog"; + +export default class SiteConfig { + userBlog: UserBlog + + domain: string + weburl: string + webtheme: string + webname: string + webslogen: string + keywords: string + description: string + beianinfo: string + + constructor() { + this.userBlog = new UserBlog(); + this.domain = "" + this.weburl = "" + this.webtheme = "default" + this.webname = "浅海拾贝" + this.webslogen = "寻找未知的技术拼图" + this.keywords = "软件架构、服务端开发、Java、Spring、Dubbo、Zookeeper、微服务" + this.description = "浅海拾贝是关注与分享互联网及服务端开发技术的个人博客,致力于Java后端开发及服务端技术、软件架构、微服务技术分享。同时也记录个人的一路点滴,所蕴含的包括前端、后端、数据库等知识,欢迎您关注我。" + this.beianinfo = "粤ICP备18023717号-1" + } +} \ No newline at end of file diff --git a/lib/common/userBlog.ts b/lib/common/userBlog.ts new file mode 100644 index 0000000..09aedd5 --- /dev/null +++ b/lib/common/userBlog.ts @@ -0,0 +1,14 @@ +export class UserBlog { + blogid: string + url: string + blogName: string + isAdmin?: boolean + xmlrpc?: string + + + constructor() { + this.blogid = ""; + this.url = ""; + this.blogName = "" + } +} \ No newline at end of file diff --git a/lib/constants.ts b/lib/constants.ts new file mode 100644 index 0000000..17c526d --- /dev/null +++ b/lib/constants.ts @@ -0,0 +1,11 @@ +/** + * 思源笔记 + */ +const API_TYPE_SIYUAN = "siyuan" + +/** + * API类型常量定义 + */ +export const API_TYPE_CONSTANTS = { + API_TYPE_SIYUAN +} \ No newline at end of file diff --git a/lib/constants/metaweblogMethodConstants.ts b/lib/constants/metaweblogMethodConstants.ts new file mode 100644 index 0000000..72bb6e2 --- /dev/null +++ b/lib/constants/metaweblogMethodConstants.ts @@ -0,0 +1,15 @@ +const GET_USERS_BLOGS = "blogger.getUsersBlogs" +const NEW_POST = "metaWeblog.newPost" +const EDIT_POST = "metaWeblog.editPost" +const DELETE_POST = "blogger.deletePost" +const GET_RECENT_POSTS = "metaWeblog.getRecentPosts" +const GET_POST = "metaWeblog.getPost" + +export const METAWEBLOG_METHOD_CONSTANTS = { + GET_USERS_BLOGS, + NEW_POST, + EDIT_POST, + DELETE_POST, + GET_RECENT_POSTS, + GET_POST +} \ No newline at end of file diff --git a/lib/constants/postStatusConstants.ts b/lib/constants/postStatusConstants.ts new file mode 100644 index 0000000..084cd50 --- /dev/null +++ b/lib/constants/postStatusConstants.ts @@ -0,0 +1,9 @@ +const POST_STATUS_PUBLISH = "publish" +const POST_TYPE_DRAFT = "draft" +const POST_TYPE_INHERIT = "inherit" + +export const POST_STATUS_CONSTANTS = { + POST_STATUS_PUBLISH, + POST_TYPE_DRAFT, + POST_TYPE_INHERIT +} \ No newline at end of file diff --git a/lib/constants/serverApiConstants.ts b/lib/constants/serverApiConstants.ts new file mode 100644 index 0000000..1462225 --- /dev/null +++ b/lib/constants/serverApiConstants.ts @@ -0,0 +1,7 @@ +const SERVER_API_GET_RECENT_POSTS = "/api/endpoint/getRecentPosts" +const SERVER_API_GET_POST = "/api/endpoint/getPost" + +export const SERVER_API_CONSTANTS = { + SERVER_API_GET_RECENT_POSTS, + SERVER_API_GET_POST +} \ No newline at end of file diff --git a/lib/htmlUtil.ts b/lib/htmlUtil.ts new file mode 100644 index 0000000..93c6271 --- /dev/null +++ b/lib/htmlUtil.ts @@ -0,0 +1,127 @@ +// const showdown = require("showdown") +// const converter = new showdown.Converter(); +// +// /** +// * 将Markdown转换为HTML +// * @param md Markdown +// * @returns {*} HTML +// */ +// export function mdToHtml(md: string) { +// let html = converter.makeHtml(md); +// return removeWidgetTag(html); +// } +// instdead by lute + +import {renderHTML} from "./markdownUtil"; + +/** + * 移除标题数字 + * @param str + */ +export function removeTitleNumber(str: string) { + let newstr = str + + // 移除序号 + const publisherRegex = /([0-9]*)\./g; + newstr = newstr.replace(publisherRegex, "") + + return newstr +} + +/** + * 删除挂件的HTML + * @param str 原字符 + * @returns {*|string} 删除后的字符 + */ +export function removeWidgetTag(str: string) { + let newstr = str + + // 旧版发布挂件 + const publisherRegex = //g; + newstr = newstr.replace(publisherRegex, "") + + // 新版发布挂件 + const syPublisherRegex = //g; + newstr = newstr.replace(syPublisherRegex, "") + + // 文章属性挂件 + const noteAttrRegex = //g + newstr = newstr.replace(noteAttrRegex, "") + + const h1Regex = //g + newstr = newstr.replace(h1Regex, "") + + return newstr +} + +/** + * 截取指定长度html + * @param html html + * @param length 长度 + * @param ignore 不要结尾省略号 + * @returns {string} 结果 + */ +export function parseHtml(html: string, length: number, ignore?: boolean) { + let allText = filterHtml(html); + if (allText.length < length) { + return allText; + } + if (ignore) { + return allText.substring(0, length); + } + return allText.substring(0, length) + "..."; +} + +/** + * 去除html标签,残缺不全也可以 + * @param str + * @returns {string} 转换后的结果 + */ +function filterHtml(str: string) { + /* + * <.*?>为正则表达式,其中的.表示任意字符,*?表示出现0次或0次以上,此方法可以去掉双头标签(双头针对于残缺的标签) + * "<.*?"表示<尖括号后的所有字符,此方法可以去掉残缺的标签,及后面的内容 + * " ",若有多种此种字符,可用同一方法去除 + */ + str = str.replace(//g, '') + str = str.replace(//g, '') + str = str.replace(/<[^>]*>/g, ''); + str = str.replace(/&.*;/g, ''); + str = str.replace(/(^\s*)|(\s*$)/g, ""); + str = str.replace(//g, "") + str = str.replace(/"/g, "").replace(/'/g, "") + + // 正则保留字符 + str = str.replace(/\*/g, "") + str = str.replace(/\$/g, "") + str = str.replace(/\./g, "") + str = str.replace(/\+/g, "") + + // 下面是行内空格,不建议去除 + str = str.replace(/\s+/g, ''); + + // 冒号分号替换成下划线 + str = str.replace(/[:|:]/g, "_") + str = str.replace(/[;|;]/g, "_") + + // 需要排除的字符 + const excludeWords = ['\\d*/\\d/\\d*', '[、|\\\\]', '[,|,]', '\\d', '/', '-'] + for (let i = 0; i < excludeWords.length; i++) { + const regex = new RegExp(excludeWords[i], "g"); + str = str.replaceAll(regex, "") + } + + str = str.toLowerCase(); + return str; +} + +/** + * 将Markdown转换为纯文本 + * @param md + * @returns {string} + */ +export function mdToPlanText(md: string) { + let html = renderHTML(md) + html = removeWidgetTag(html) + return filterHtml(html) +} \ No newline at end of file diff --git a/lib/logUtil.ts b/lib/logUtil.ts new file mode 100644 index 0000000..0ee9d30 --- /dev/null +++ b/lib/logUtil.ts @@ -0,0 +1,63 @@ +// 开发阶段开启所有日志 +// 发布阶段只开启WARN和ERROR日志 + +const LOG_INFO_ENABLED = true +const LOG_WARN_ENABLED = true +const LOG_ERROR_ENABLED = true + +/** + * 信息日志 + * @param msg 信息 + * @param param 参数 + */ +const logInfo = (msg: any, param?: any) => { + if (LOG_INFO_ENABLED) { + if (param) { + console.log(msg) + console.log(param) + } else { + console.log(msg) + } + } +} +/** + * 警告日志 + * @param msg 警告信息 + * @param param 参数 + */ +const logWarn = (msg: any, param?: any) => { + if (LOG_WARN_ENABLED) { + if (param) { + console.warn(msg) + console.warn(param) + } else { + console.warn(msg) + } + } +} +/** + * 错误日志 + * @param msg 错误信息 + * @param param 参数 + */ +const logError = (msg: any, param?: any) => { + if (LOG_ERROR_ENABLED) { + if (param) { + console.error(msg) + console.error(param) + } else { + console.error(msg) + } + } +} + +/** + * 日志记录 + */ +const logUtil = { + logInfo, + logWarn, + logError +} + +export default logUtil \ No newline at end of file diff --git a/lib/markdownUtil.ts b/lib/markdownUtil.ts new file mode 100644 index 0000000..544fb28 --- /dev/null +++ b/lib/markdownUtil.ts @@ -0,0 +1,11 @@ +import Showdown from "showdown" + +const converter = new Showdown.Converter() + +/** + * 渲染Markdown + * @param md + */ +export function renderHTML(md: string) { + return converter.makeHtml(md); +} \ No newline at end of file diff --git a/lib/siyuan/siYuanApi.ts b/lib/siyuan/siYuanApi.ts new file mode 100644 index 0000000..e3468e9 --- /dev/null +++ b/lib/siyuan/siYuanApi.ts @@ -0,0 +1,150 @@ +import logUtil from "~/lib/logUtil"; + +/** + * 思源API v2.0.27 + * + * @author terwer + * @date 2022-08-02 23:17 + * + * https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md#%E9%89%B4%E6%9D%83 + */ +export class SiYuanApi { + private readonly env: any + + constructor(env: any) { + this.env = env; + } + + /** + * 分页获取根文档 + * @param page 页码 + * @param pagesize 数目 + * @param keyword 关键字 + */ + public async getRootBlocks(page: number, pagesize: number, keyword: string) { + let stmt = `SELECT b.content, tmp.root_id + FROM (SELECT DISTINCT root_id + FROM blocks + WHERE 1 = 1 + AND content LIKE '%${keyword}%' + ORDER BY created DESC LIMIT ${page}, ${pagesize}) tmp, + blocks b + WHERE tmp.root_id = b.root_id + AND b.parent_id = '' + ORDER BY b.created DESC` + return await this.sql(stmt) + } + + /** + * 获取块属性 + * @param blockId + */ + public async getBlockAttrs(blockId: string) { + let data = { + id: blockId, + } + let url = '/api/attr/getBlockAttrs' + return this.siyuanRequest(url, data) + } + + /** + * 设置块属性 + * @param blockId + * @param attrs + */ + public async setBlockAttrs(blockId: string, attrs: any) { + let url = '/api/attr/setBlockAttrs' + return this.siyuanRequest(url, { + id: blockId, + attrs: attrs, + }) + } + + /** + * 以id获取思源块信息 + * @param blockId 内容块ID + */ + public async getBlockByID(blockId: string) { + let stmt = `select * + from blocks + where id = '${blockId}'` + let data = await this.sql(stmt) + console.log(data) + return data[0] + } + + /** + * 以slug获取思源块信息 + * @param slug 内容块别名 + */ + public async getBlockBySlug(slug: string) { + let stmt = `select root_id from attributes + where name='custom-slug' and value='${slug}' + limit 1` + let data = await this.sql(stmt) + console.log(data) + return data[0] + } + + /** + * 导出markdown文本 + * @param docId 文档id + */ + public async exportMdContent(docId: string) { + let data = { + id: docId, + } + let url = '/api/export/exportMdContent' + return this.siyuanRequest(url, data) + //文档hepath与Markdown 内容 + } + + /** + * 向思源请求数据 + * @param url url + * @param data 数据 + * @param method 请求方法 GET | POST + * @param useToken 权限TOKEN + */ + private async siyuanRequest(url: string, data: any, method?: string, useToken?: boolean) { + if (this.env.SIYUAN_API_URL != "") { + url = this.env.SIYUAN_API_URL + url + } + + let m = "POST" + if (method) { + m = method; + } + + let fetchOps = { + body: JSON.stringify(data), + method: m + } + if (useToken != false) { + Object.assign(fetchOps, { + headers: { + "Authorization": `Token ${this.env.SIYUAN_AUTH_TOKEN}`, + } + }) + } + + logUtil.logInfo("向思源请求数据,url=>", url) + logUtil.logInfo("向思源请求数据,fetchOps=>", fetchOps) + const response = await fetch(url, fetchOps) + const result: any = await response.json() + logUtil.logInfo("向思源请求数据,result=>", result) + return result.code === 0 ? result.data : null + } + + /** + * 以sql发送请求 + * @param sql sql + */ + private async sql(sql: string) { + let sqldata = { + stmt: sql, + } + let url = '/api/query/sql' + return this.siyuanRequest(url, sqldata) + } +} \ No newline at end of file diff --git a/lib/siyuan/siYuanApiAdaptor.ts b/lib/siyuan/siYuanApiAdaptor.ts new file mode 100644 index 0000000..2ade620 --- /dev/null +++ b/lib/siyuan/siYuanApiAdaptor.ts @@ -0,0 +1,129 @@ +import {Post} from "~/lib/common/post"; +import {UserBlog} from "~/lib/common/userBlog"; +import {API_TYPE_CONSTANTS} from "~/lib/constants"; +import {removeTitleNumber, removeWidgetTag} from "~/lib/htmlUtil"; +import {SiYuanApi} from "~/lib/siyuan/siYuanApi"; +import {IApi} from "~/lib/api"; +import {renderHTML} from "~/lib/markdownUtil"; + +/** + * 思源笔记API适配器 + */ +export class SiYuanApiAdaptor implements IApi { + private readonly env: any + private readonly siyuanApi: SiYuanApi + + constructor(env: any) { + this.env = env; + this.siyuanApi = new SiYuanApi(env) + } + + public async getUsersBlogs(): Promise> { + let result: Array = [] + // const data = await this.metaWeblog.getUsersBlogs(this.appkey, this.username, this.password); + const userBlog = new UserBlog() + userBlog.blogid = API_TYPE_CONSTANTS.API_TYPE_SIYUAN + userBlog.blogName = API_TYPE_CONSTANTS.API_TYPE_SIYUAN + userBlog.url = this.env.SIYUAN_API_URL || "" + result.push(userBlog) + + return result; + } + + public async getRecentPosts(numOfPosts: number, page: number, keyword?: string): Promise> { + let result: any[] = [] + + let pg = 0 + if (page) { + pg = page + } + let k = keyword || "" + const siyuanPosts: any = await this.siyuanApi.getRootBlocks(pg, numOfPosts, k) + // log.logInfo(siyuanPosts) + + for (let i = 0; i < siyuanPosts.length; i++) { + const siyuanPost = siyuanPosts[i] + + // 某些属性详情页控制即可 + const attrs: any = await this.siyuanApi.getBlockAttrs(siyuanPost.root_id) + + // // 发布状态 + // let isPublished = true + // const publishStatus = attrs["custom-publish-status"] || "draft" + // if (publishStatus == "secret") { + // isPublished = false; + // } + // + // // 访问密码 + // const postPassword = attrs["custom-publish-password"] || "" + + // 文章别名 + const customSlug = attrs["custom-slug"] || "" + + let title = siyuanPost.content || "" + title = removeTitleNumber(title) + + // 适配公共属性 + let commonPost = new Post() + commonPost.postid = siyuanPost.root_id + commonPost.title = title + commonPost.permalink = customSlug == "" ? "/post/" + siyuanPost.root_id : "/post/" + customSlug + ".html" + // commonPost.isPublished = isPublished + // commonPost.mt_keywords = attrs.tags || "" + result.push(commonPost) + } + + return Promise.resolve(result); + } + + public async getPost(postid: string, useSlug?: boolean): Promise { + let pid = postid + if (useSlug) { + const pidObj: any = await this.siyuanApi.getBlockBySlug(postid) + if (pidObj) { + pid = pidObj.root_id + } + } + const siyuanPost: any = await this.siyuanApi.getBlockByID(pid) + if (!siyuanPost) { + throw new Error("文章不存存在,postid=>" + pid) + } + + const attrs: any = await this.siyuanApi.getBlockAttrs(pid) + const md: any = await this.siyuanApi.exportMdContent(pid) + + // 发布状态 + let isPublished = true + const publishStatus = attrs["custom-publish-status"] || "draft" + if (publishStatus == "secret") { + isPublished = false; + } + + // 访问密码 + const postPassword = attrs["custom-post-password"] || "" + + // 访问密码 + const shortDesc = attrs["custom-desc"] || "" + + // 渲染Markdown + let html = renderHTML(md.content) + // 移除挂件html + html = removeWidgetTag(html) + + let title = siyuanPost.content || "" + title = removeTitleNumber(title) + + // 适配公共属性 + let commonPost = new Post() + commonPost.postid = siyuanPost.root_id || "" + commonPost.title = title + commonPost.description = html || "" + commonPost.shortDesc = shortDesc || "" + commonPost.mt_keywords = attrs.tags || "" + commonPost.isPublished = isPublished + commonPost.wp_password = postPassword + // commonPost.dateCreated + + return commonPost + } +} \ No newline at end of file diff --git a/package.json b/package.json index 5bac513..f5ef74a 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,10 @@ "preview": "nuxt preview" }, "devDependencies": { + "@types/showdown": "^2.0.0", "nuxt": "3.0.0-rc.8" + }, + "dependencies": { + "showdown": "^2.1.0" } } diff --git a/pages/index.vue b/pages/index.vue new file mode 100644 index 0000000..fa1b72b --- /dev/null +++ b/pages/index.vue @@ -0,0 +1,32 @@ + + + + + + + \ No newline at end of file diff --git a/pages/post.vue b/pages/post.vue new file mode 100644 index 0000000..5466e48 --- /dev/null +++ b/pages/post.vue @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/server/api/endpoint/getPost.ts b/server/api/endpoint/getPost.ts new file mode 100644 index 0000000..20a2f70 --- /dev/null +++ b/server/api/endpoint/getPost.ts @@ -0,0 +1,20 @@ +import {API_TYPE_CONSTANTS} from "~/lib/constants"; +import {API} from "~/lib/api"; + +export default defineEventHandler(async (event) => { + const type = API_TYPE_CONSTANTS.API_TYPE_SIYUAN + const postid = "20220822195304-l7nucpp" + + const env = useRuntimeConfig() + console.log('Runtime env:', env) + + const api = new API(type, env) + + const result = await api.getPost(postid) + + return { + code: 0, + msg: "操作成功", + data: result + } +}) \ No newline at end of file diff --git a/server/api/endpoint/getRecentPosts.ts b/server/api/endpoint/getRecentPosts.ts new file mode 100644 index 0000000..5655556 --- /dev/null +++ b/server/api/endpoint/getRecentPosts.ts @@ -0,0 +1,22 @@ +import {API_TYPE_CONSTANTS} from "~/lib/constants"; +import {API} from "~/lib/api"; + +export default defineEventHandler(async (event) => { + const type = API_TYPE_CONSTANTS.API_TYPE_SIYUAN + const num = 10 + const page = 1 + const keyword = "" + + const env = useRuntimeConfig() + console.log('Runtime env:', env) + + const api = new API(type, env) + + const result = await api.getRecentPosts(num, page, keyword) + + return { + code: 0, + msg: "操作成功", + data: result + } +}) \ No newline at end of file diff --git a/server/api/hello.ts b/server/api/hello.ts new file mode 100644 index 0000000..1bb733e --- /dev/null +++ b/server/api/hello.ts @@ -0,0 +1,7 @@ +export default defineEventHandler((event) => { + + + return { + api: 'works' + } +}) \ No newline at end of file diff --git a/server/middleware/log.ts b/server/middleware/log.ts new file mode 100644 index 0000000..a1746ca --- /dev/null +++ b/server/middleware/log.ts @@ -0,0 +1,3 @@ +export default defineEventHandler((event) => { + console.log('New request: ' + event.req.url) +}) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 66ee76f..5bf4f16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -640,6 +640,11 @@ dependencies: "@types/node" "*" +"@types/showdown@^2.0.0": + version "2.0.0" + resolved "https://registry.npmmirror.com/@types/showdown/-/showdown-2.0.0.tgz#3e800eca8573848cac4e5555f4377ba3a0e7b1f2" + integrity sha512-70xBJoLv+oXjB5PhtA8vo7erjLDp9/qqI63SRHm4REKrwuPOLs8HhXwlZJBJaB4kC18cCZ1UUZ6Fb/PLFW4TCA== + "@types/tough-cookie@*": version "4.0.2" resolved "https://registry.npmmirror.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" @@ -1231,6 +1236,11 @@ commander@^8.0.0: resolved "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^9.0.0: + version "9.4.0" + resolved "https://registry.npmmirror.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c" + integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3733,6 +3743,13 @@ shebang-regex@^3.0.0: resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +showdown@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/showdown/-/showdown-2.1.0.tgz#1251f5ed8f773f0c0c7bfc8e6fd23581f9e545c5" + integrity sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ== + dependencies: + commander "^9.0.0" + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"