refactor: 重構後端代碼, 換用 Deno

This commit is contained in:
CrescentLeaf
2025-06-15 00:22:53 +08:00
parent 6c225b7bc5
commit d65ead11e1
29 changed files with 362 additions and 15645 deletions

View File

@@ -1,39 +0,0 @@
export class TheWhiteSilkParams {
/**
* @type { String }
*/
method
/**
* @type { Object }
*/
args
}
export class CallbackMessage {
static Code = class {
/**
* 无权限
*/
static PERMISSION_DENIED = 401
/**
* 不存在
*/
static NOT_FOUND = 404
/**
* 服务端错误
*/
static SERVER_ERROR = 500
/**
* 请求成功
*/
static OK = 200
}
/**
* @type { String }
*/
msg
/**
* @type { Number }
*/
code
}

View File

@@ -1,55 +0,0 @@
import io from '../lib/io.js';
import { sha256 } from '../lib/crypto.js'
const baseDir = 'whitesilk_data/chat'
io.mkdirs(baseDir)
export class ChatManager {
/**
* 获取私聊实例 (双方可对调)
* @param { String } a 用户A 的 ID
* @param { String } b 用户B 的 ID
* @returns { Chat }
*/
static getPrivateChat(a, b) {
let id = sha256([
a,
b,
].sort().join())
io.mkdirs(`${baseDir}/${id}`)
let chat = new Chat(id)
chat.id = id
chat.updateInfo()
return chat
}
}
export class Chat {
constructor(id) {
if (!io.exists(`${baseDir}/${id}`)) throw new Error(`聊天 [id=${id}]不存在!`)
// 尽管所有的键都是 undefined 但是仍然是键哦
for (let k of Object.keys(this)) {
this[k] = io.open(`${baseDir}/${id}/${k}`, 'rw').checkExistsOrWrite('').readAllAndClose().toString()
}
}
updateInfo() {
// 尽管所有的键都是 undefined 但是仍然是键哦
for (let k of Object.keys(this)) {
io.open(`${baseDir}/${this.id}/${k}`, 'w').writeAll((this[k] || '') + '').close()
}
// 防止服务端错误修改此值 主要是都是属性了再搞特殊对待很麻烦的
io.open(`${baseDir}/${this.id}/id`, 'w').writeAll(this.id + '').close()
}
/**
* 聊天 ID
* @type { String }
*/
id
}
export class ChatApi {
static createUser() {
}
}

View File

@@ -1,139 +0,0 @@
import io from '../lib/io.js';
import { sha256 } from '../lib/crypto.js'
import { CallbackMessage } from '../Types.js';
const baseDir = 'whitesilk_data/user'
io.mkdirs(baseDir)
export class UserManager {
static getUserProfileDir(id) {
return `${baseDir}/${id}`
}
static getUserById(id) {
return new User(id)
}
static getUserByName(name) {
let list = io.listFolders(baseDir, {
fullPath: false,
})
}
/**
* 创建新用户
* @param { Object } arg
* @param { String } [arg.name] 用户名
* @returns { User }
*/
static createUser({ name } = {}) {
let idCountFile = io.open(`${baseDir}/idcount`, 'rw').checkExistsOrWrite('10000')
let idCount = parseInt(idCountFile.readAll())
io.mkdirs(`${baseDir}/${idCount}`)
idCount++
idCountFile.writeAll(idCount + '').close()
idCount--
let user = new User(idCount)
user.id = idCount
user.name = name
user.updateProfile()
return user
}
}
export class User {
constructor(id) {
if (!io.exists(`${baseDir}/${id}`)) throw new Error(`用户 [id=${id}]不存在!`)
// 尽管所有的键都是 undefined 但是仍然是键哦
for (let k of Object.keys(this)) {
this[k] = io.open(`${baseDir}/${id}/${k}`, 'rw').checkExistsOrWrite('').readAllAndClose().toString()
}
}
updateProfile() {
// 尽管所有的键都是 undefined 但是仍然是键哦
for (let k of Object.keys(this)) {
io.open(`${baseDir}/${this.id}/${k}`, 'w').writeAll((this[k] || '') + '').close()
}
// 防止服务端错误修改此值 主要是都是属性了再搞特殊对待很麻烦的
io.open(`${baseDir}/${this.id}/id`, 'w').writeAll(this.id + '').close()
}
/**
* 设置头像
* @param { Buffer } data 头像数据
*/
setAvatar(data) {
io.open(`${baseDir}/${this.id}/avatar`, 'w').writeAll(data).close()
}
/**获取头像
* @returns { Buffer } data 头像数据
*/
getAvatar() {
return io.open(`${baseDir}/${this.id}/avatar`, 'r').readAllAndClose()
}
/**
* 用户 ID
* @type { String }
*/
id
/**
* 用户名
* @type { String }
*/
name
/**
* 用户昵称
* @type { String }
*/
nick
/**
* 用户简介
* @type { String }
*/
description
/**
* 密码(经过加盐哈希处理后的 哈希后的密码)
* @type { String }
*/
passwordHashed
}
export const UserApi = {
API_NAME: 'UserApi',
/**
* 注册用户
* @param { Object } args
* @param { String } args.name 用户名(必须, 注册后可以删除)
* @param { String } args.password 密码(哈希后)
* @returns { CallbackMessage }
*/
["createUser"]: (args) => {
// TODO: 想办法解决账号注册的问题
// 思路之一: 扫名称 重复则不允许
// 思路之二: 邮箱制 但是无法多账号 以及其他遗留问题
// 长远思考
// 2025.6.2 決定
// 使用郵箱驗證, 以賬號ID為基準, 用戶名可改但不可重複制度
// 關聯性字符串數據庫
// 具體方案: 先使用郵箱驗證
// 再注冊賬號
// 賬號支持修改不重複的用戶名
// 可以一個郵箱多個賬號
// 修改郵箱 = 修改文件名
// 多賬號管理 = 郵箱 (文件夾) + 多賬戶ID
// 忘記賬號 = 郵箱驗證 + 給出所有賬號
let user = UserManager.createUser({
name: args.name,
})
user.passwordHashed = sha256('我是盐 这个后面会给成配置文件来配置的喵~' + args.password)
user.updateProfile()
return {
msg: '🥰🥰🥰🥰🥰',
code: CallbackMessage.Code.OK,
data: args,
}
},
}

View File

@@ -1,7 +1,8 @@
// @ts-types="npm:@types/babel__core"
import babel from '@babel/core'
import io from './lib/io.js'
function compileJs(path) {
function compileJs(path: string) {
babel.transformFileAsync(path, {
presets: [
[
@@ -22,13 +23,14 @@ function compileJs(path) {
},
sourceMaps: true,
}).then(function (result) {
if (result == null) throw new Error('result == null')
io.open(path, 'w').writeAll(result.code + '\n' + `//@ sourceMappingURL=${io.getName(path)}.map`).close()
io.open(path + '.map', 'w').writeAll(JSON.stringify(result.map)).close()
console.log(`Compile js: ${path}`)
})
}
export default function (path) {
export default function (path: string) {
io.listFiles(path, {
recursive: true,
fullPath: true,

13
server/config.ts Normal file
View File

@@ -0,0 +1,13 @@
import io from './lib/io.js'
export default class Config {
static ensureAllDirsAreCreated() {
for (const key of Object.keys(Config.dirs)) {
io.mkdirs(Config.dirs[key])
}
}
static BASE_DIR = 'whitesilk'
static dirs : { [key: string]: string } = {
WEB_PAGE_DIR: this.BASE_DIR + '/_webpage'
}
}

View File

@@ -1,50 +0,0 @@
import http from 'node:http'
// import https from 'node:https' // 暂时
import express from 'express'
import { Server as SocketIoServer } from 'socket.io'
// 类型提示
import { TheWhiteSilkParams, CallbackMessage } from './Types.js'
const app = express()
const httpApp = http.createServer(app)
const sio = new SocketIoServer(httpApp, {})
// 编译前端代码
import io from './lib/io.js'
io.copyDir('./client/', './whitesilk_data/page_builded/')
await import('./build.js').then(a => a.default('whitesilk_data/page_builded/'))
app.use('/', express.static('whitesilk_data/page_builded/'))
const events = {}
import { UserApi } from './api/User.js'
for (let i of [
UserApi,
]) {
for (let i2 of Object.keys(i)) {
if (i2 == 'API_NAME') continue
events[i.API_NAME + '.' + [i2]] = i[i2]
}
}
sio.on("connection", (socket) => {
socket.on('the_white_silk',
/**
* @param { TheWhiteSilkParams } params
* @param { Function } callback
*/
(params, callback) => {
if ((params || callback) == null || typeof callback != 'function') return;
/** @type { CallbackMessage } */
let data = events[params.method] ? events[params.method](params.args) : {
msg: '找不到此方法',
code: CallbackMessage.Code.NOT_FOUND,
}
callback(data)
}
)
})
httpApp.listen(80)