Waline 评论系统折腾记录
开端
最近正在研究夸父的评论系统。国庆之后有过一段调研,当时了解到了 Waline ,但现在已经忘光,所以从零开始继续学习 Waline 的用法。写这篇文章是因为捣鼓 Waline 的时候遇到了太多困难,发一篇牢骚(谁叫自己造轮子太困难了呢。
发现异常
想要直接部署这个服务非常简单,但想要自定义它的一些功能非常困难。虽然官方有说明支持自定义部分功能,但一系列问题还是让我摸不着头脑:
官方提供的运行方法让自定义看上去不太可能:
这是在直接运行库内的 JS 文件,难道我要去修改他们的包吗
官方提供的文档看上去没有入口函数:
只有一个 module.exports ,却没有说明在哪里使用这个模块,也没有提供运行命令
自定义操作复杂繁琐:
如上面的自定义用户系统,它说可以用“自定义数据库服务”来实现这个功能,于是去查看自定义数据库文档
这个文档刚开始比较难读懂,但读懂之后明白了它的意思:
我们的项目使用的是 Prisma ,这让难度更加上升(暂且不谈函数的执行方法)。我需要有一个数据库,用来执行
prisma migrate
,还要和我们的主项目同步 Prisma Schema 。这才会生成对应的 PrismaClient 。然后我就可以写出类似如下的代码:红框部分是官方给出的参考类型
函数执行方法复杂:
因为我需要把它传入的参数做一个转换,使其作为 Prisma 的查询条件。这是官方给的查询方法实例:
普通查询:
const model = new CustomModel('Comment'); await model.select({ url: '/', user_id: ['!=', 0], createdAt: ['>', '2023-04-16 00:00:00'], }); // SELECT * FROM Comment WHERE url = '/' AND user_id != 0 AND createdAt > "2023-04-16 00:00:00";
IN / NOT IN 查询
const model = new CustomModel('Users'); await model.select({ objectId: ['IN', [1, 2, 3, 4]] }); // SELECT * FROM Users WHERE objectId IN (1,2,3,4);
const model = new CustomModel('Comment'); await model.select({ status: ['NOT IN', ['waiting', 'spam']] }); // SELECT * FROM Comment WHERE status NOT IN ('waiting', 'spam');
LIKE 查询
const model = new CustomModel('Comment'); await model.select({ content: ['LIKE', '%content%'] }); // SELECT * FROM Comment WHERE content LIKE "%content%";
多条件查询
const model = new CustomModel('Comment'); await model.select({ url: '/', user_id: ['!=', 0], createdAt: ['>', '2023-04-16 00:00:00'], _logic: 'OR', }); // SELECT * FROM Comment WHERE url = '/' OR user_id != 0 OR createdAt > "2023-04-16 00:00:00";
复合查询
const model = new CustomModel('Comment'); await model.select({ url: '/', _complex: { user_id: 0, status: ['NOT IN', ['waiting', 'spam']] _logic: 'OR' } }); // SELECT * FROM Comment WHERE url = '/' AND ( user_id = 0 OR status NOT IN ('waiting', 'spam'));
如果你比较熟悉 TypeScript,这里有条件查询的类型定义。
搏斗过程
对 Vercel 的困惑
我发现它对 Vercel 有着很好的支持,甚至这样就可以在 Vercel 上直接运行:
这看上去也没有入口函数,可是为什么 Vercel 却可以直接运行呢。
尤其是 GPT 给出的回答,让我更加好奇:
Vercel 是一个云平台,专门为前端项目和无服务器(Serverless)函数提供部署和托管服务。
当您在本地使用 Vercel CLI 运行 vercel dev 命令时,它模拟了 Vercel 云环境的行为,
让您能够在本地开发和测试无服务器函数。
目前还没有这个精力去研究 Vercel ,留下这个困惑,之后再去和 Vercel 搏斗(
如何运行
所以话说回来,我应该如何在本地运行的同时,又能引入我的自定义模块呢?
又经过一段时间的折腾,我尝试使用 express 来进行模拟。
#初次尝试(失败
第一次是按照官方的方法,使用 module.exports :
然后在 express 挂在 Application 路由:
结果以失败告终。
成功尝试
然后我换了一种方法,把 module.exports 改为一个变量接收,然后再把该变量放入 express 路由中,结果成功了!
代码如下:
import dotenv from "dotenv";
dotenv.config();
import UserModel from "./userModel";
import express from "express";
const Application = require("@waline/vercel");
const bcrypt = require("bcrypt");
const MyApplication = Application({
model(tableName: string) {
if (tableName !== "Users") {
return;
}
return new UserModel();
},
encryptPassword() {
return {
async hashPassword(password: any) {
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds);
return hashedPassword;
},
async checkPassword(password: any, storeHash: any) {
const isPasswordValid = await bcrypt.compare(password, storeHash);
return isPasswordValid;
},
};
},
});
const app = express();
const PORT = process.env.PORT || 3000;
app.use("/", MyApplication);
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
运行成功截图
运行成功截图
但事情似乎还没完….
成功运行不代表能用
网站虽然跑起来了,但注册等基础功能并不可用,还需要继续折腾。
初步判断是由于数据库映射有问题,于是改写代码后再次尝试。发现还是运行不了。
于是在每个函数中增加 console.log ,发现控制台并没有输出,而且请求根本发送不出去,甚至连我没有改写的 comment 请求也无法发出:
而且意料之中的,我改写的 user model 也无法正常使用 :
再次怀疑运行方法
现在把怀疑对象转为我折腾出来的 express 启动方法。看起来这个方法并不能正常启动所需服务。
查看源码之后发现入口文件长这样:
应该是一个突破口。于是把源码拿下来,并在源码上进行修改之后,成功运行,但数据库的映射并没有实现。
再次检查代码发现有个地方出错,更改之后我的自定义部分有效果了,但是是错误效果。
由于之前是根据官网改的 index.js 文件,现在发现 vanilla.js 中也有类似代码,然后我擅自在里面加上一模一样的更改,结果成功运行,但数据库映射没有起作用。看来只能在成功运行和自定义模块起作用这两个中二选一了。。
结束
这让我深刻了解一件事情:本来开源就是个公益事,写不写文档都是随缘的