Refactor code structure for improved readability and maintainability

This commit is contained in:
2026-01-11 15:51:22 +07:00
parent 6f8a8de9be
commit 309606565b
46 changed files with 28649 additions and 28522 deletions

View File

@@ -51,23 +51,23 @@ curl https://your-domain.com/version.json
```typescript
// Node.js / Elysia 示例
app.get('/api/app/version', async (ctx) => {
app.get("/api/app/version", async (ctx) => {
// 从前端静态资源读取版本
const response = await fetch('https://your-frontend-domain.com/version.json')
const frontendVersion = await response.json()
const { platform, currentVersion } = ctx.query
const response = await fetch("https://your-frontend-domain.com/version.json");
const frontendVersion = await response.json();
const { platform, currentVersion } = ctx.query;
return {
version: frontendVersion.version,
forceUpdate: compareVersion(currentVersion, frontendVersion.version) < 0,
updateMessage: '修复了一些问题',
updateUrl: platform === 'ios'
? 'https://apps.apple.com/app/xxx'
: 'https://play.google.com/store/apps/details?id=xxx',
minSupportVersion: '0.0.1',
}
})
updateMessage: "修复了一些问题",
updateUrl: platform === "ios"
? "https://apps.apple.com/app/xxx"
: "https://play.google.com/store/apps/details?id=xxx",
minSupportVersion: "0.0.1",
};
});
```
**方式 2部署时同步到后端**
@@ -88,18 +88,18 @@ app.get('/api/app/version', async (ctx) => {
后端直接读取本地文件:
```typescript
import fs from 'fs'
import fs from "node:fs";
app.get("/api/app/version", async (ctx) => {
const versionFile = fs.readFileSync("/app/frontend-version.json", "utf-8");
const { version } = JSON.parse(versionFile);
app.get('/api/app/version', async (ctx) => {
const versionFile = fs.readFileSync('/app/frontend-version.json', 'utf-8')
const { version } = JSON.parse(versionFile)
return {
version,
forceUpdate: false,
// ...
}
})
};
});
```
---
@@ -112,7 +112,7 @@ app.get('/api/app/version', async (ctx) => {
```json
{
"version": "1.2.3" // 只改这里
"version": "1.2.3" // 只改这里
}
```
@@ -162,27 +162,27 @@ versionName "1.2.3" // 与 package.json 保持一致
```javascript
#!/usr/bin/env node
import fs from 'fs'
import { execSync } from 'child_process'
import { execSync } from "node:child_process";
import fs from "node:fs";
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf-8'))
const version = packageJson.version
const packageJson = JSON.parse(fs.readFileSync("./package.json", "utf-8"));
const version = packageJson.version;
console.log(`Syncing version ${version} to native projects...`)
console.log(`Syncing version ${version} to native projects...`);
// iOS
const infoPlist = './ios/App/App/Info.plist'
let plistContent = fs.readFileSync(infoPlist, 'utf-8')
const infoPlist = "./ios/App/App/Info.plist";
let plistContent = fs.readFileSync(infoPlist, "utf-8");
plistContent = plistContent.replace(
/<key>CFBundleShortVersionString<\/key>\s*<string>.*?<\/string>/,
`<key>CFBundleShortVersionString</key>\n\t<string>${version}</string>`
)
fs.writeFileSync(infoPlist, plistContent)
);
fs.writeFileSync(infoPlist, plistContent);
// Android (需要安装 gradle 解析库或手动更新)
console.log('Please manually update android/app/build.gradle versionName')
console.log("Please manually update android/app/build.gradle versionName");
console.log('✓ Version synced!')
console.log("✓ Version synced!");
```
`package.json` 中添加脚本:
@@ -237,24 +237,24 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
node-version: "18"
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build
env:
NODE_ENV: production
- name: Deploy to server
run: |
rsync -avz dist/ user@server:/var/www/html/
- name: Notify backend
run: |
curl -X POST https://your-backend.com/api/webhook/frontend-deployed \
@@ -284,107 +284,108 @@ jobs:
**一次配置,永久受益!** 🎉
## 后端 API 实现示例 - 版本检查接口
```ts
import { Elysia, t } from 'elysia'
// 方案二:从本地文件读取(适用于前后端部署在同一服务器)
import fs from "node:fs";
import { Elysia, t } from "elysia";
// 版本比较工具函数
function compareVersion(version1: string, version2: string): number {
const v1Parts = version1.split('.').map(Number)
const v2Parts = version2.split('.').map(Number)
const maxLength = Math.max(v1Parts.length, v2Parts.length)
const v1Parts = version1.split(".").map(Number);
const v2Parts = version2.split(".").map(Number);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
for (let i = 0; i < maxLength; i++) {
const v1Part = v1Parts[i] || 0
const v2Part = v2Parts[i] || 0
const v1Part = v1Parts[i] || 0;
const v2Part = v2Parts[i] || 0;
if (v1Part < v2Part) return -1
if (v1Part > v2Part) return 1
if (v1Part < v2Part)
return -1;
if (v1Part > v2Part)
return 1;
}
return 0
return 0;
}
// 方案一:从前端静态资源读取版本(推荐)
async function getFrontendVersionFromURL(): Promise<{
version: string
buildTime: string
gitCommit: string
environment: string
version: string;
buildTime: string;
gitCommit: string;
environment: string;
}> {
const response = await fetch('https://your-frontend-domain.com/version.json')
return await response.json()
const response = await fetch("https://your-frontend-domain.com/version.json");
return await response.json();
}
// 方案二:从本地文件读取(适用于前后端部署在同一服务器)
import fs from 'fs'
function getFrontendVersionFromFile(): {
version: string
buildTime: string
gitCommit: string
environment: string
version: string;
buildTime: string;
gitCommit: string;
environment: string;
} {
const content = fs.readFileSync('/app/frontend-version.json', 'utf-8')
return JSON.parse(content)
const content = fs.readFileSync("/app/frontend-version.json", "utf-8");
return JSON.parse(content);
}
// 应用商店链接配置
const APP_STORE_URLS = {
ios: 'https://apps.apple.com/app/id123456789',
android: 'https://play.google.com/store/apps/details?id=riwa.ionic.app',
}
ios: "https://apps.apple.com/app/id123456789",
android: "https://play.google.com/store/apps/details?id=riwa.ionic.app",
};
// 版本策略配置(可存储在数据库)
const VERSION_POLICIES = {
minSupportVersion: '0.0.1', // 最低支持版本
forceUpdateVersions: ['0.0.1'], // 需要强制更新的版本列表
minSupportVersion: "0.0.1", // 最低支持版本
forceUpdateVersions: ["0.0.1"], // 需要强制更新的版本列表
updateMessages: {
'zh-CN': '修复了一些问题并优化了性能',
'en-US': 'Bug fixes and performance improvements',
"zh-CN": "修复了一些问题并优化了性能",
"en-US": "Bug fixes and performance improvements",
},
}
};
// Elysia 路由定义
const app = new Elysia()
.get(
'/api/app/version',
"/api/app/version",
async ({ query, headers }) => {
const { platform, currentVersion } = query
const lang = headers['accept-language']?.split(',')[0] || 'en-US'
const { platform, currentVersion } = query;
const lang = headers["accept-language"]?.split(",")[0] || "en-US";
try {
// 获取前端版本信息
const frontendVersion = await getFrontendVersionFromURL()
const frontendVersion = await getFrontendVersionFromURL();
// 或使用本地文件: const frontendVersion = getFrontendVersionFromFile()
// 判断是否需要更新
const hasUpdate = compareVersion(currentVersion, frontendVersion.version) < 0
const hasUpdate = compareVersion(currentVersion, frontendVersion.version) < 0;
// 判断是否强制更新
let forceUpdate = VERSION_POLICIES.forceUpdateVersions.includes(currentVersion)
let forceUpdate = VERSION_POLICIES.forceUpdateVersions.includes(currentVersion);
// 检查是否低于最低支持版本
if (compareVersion(currentVersion, VERSION_POLICIES.minSupportVersion) < 0) {
forceUpdate = true
forceUpdate = true;
}
// 获取更新链接
const updateUrl = platform === 'ios'
? APP_STORE_URLS.ios
: platform === 'android'
const updateUrl = platform === "ios"
? APP_STORE_URLS.ios
: platform === "android"
? APP_STORE_URLS.android
: ''
: "";
// 获取更新说明(多语言)
const updateMessage = VERSION_POLICIES.updateMessages[lang]
|| VERSION_POLICIES.updateMessages['en-US']
const updateMessage = VERSION_POLICIES.updateMessages[lang]
|| VERSION_POLICIES.updateMessages["en-US"];
return {
version: frontendVersion.version,
buildNumber: parseInt(frontendVersion.version.replace(/\./g, '')),
buildNumber: Number.parseInt(frontendVersion.version.replace(/\./g, "")),
buildTime: frontendVersion.buildTime,
gitCommit: frontendVersion.gitCommit,
forceUpdate,
@@ -392,26 +393,27 @@ const app = new Elysia()
updateUrl,
minSupportVersion: VERSION_POLICIES.minSupportVersion,
releaseNotes: [
'修复了已知问题',
'优化了应用性能',
'改进了用户界面',
"修复了已知问题",
"优化了应用性能",
"改进了用户界面",
],
}
} catch (error) {
console.error('Failed to get frontend version:', error)
};
}
catch (error) {
console.error("Failed to get frontend version:", error);
// 降级处理:返回当前版本,不强制更新
return {
version: currentVersion,
forceUpdate: false,
updateMessage: '',
updateUrl: '',
}
updateMessage: "",
updateUrl: "",
};
}
},
{
query: t.Object({
platform: t.Union([t.Literal('ios'), t.Literal('android'), t.Literal('web')]),
platform: t.Union([t.Literal("ios"), t.Literal("android"), t.Literal("web")]),
currentVersion: t.String(),
}),
response: t.Object({
@@ -426,13 +428,13 @@ const app = new Elysia()
releaseNotes: t.Optional(t.Array(t.String())),
}),
}
)
);
export default app
export default app;
/**
* 使用示例:
*
*
* 1. 启动后端服务
* 2. 前端请求GET /api/app/version?platform=ios&currentVersion=0.0.1
* 3. 后端响应:
@@ -448,9 +450,9 @@ export default app
/**
* 数据库存储方案(可选)
*
*
* 如果需要更灵活的版本策略管理,可以将配置存储在数据库:
*
*
* CREATE TABLE app_versions (
* id SERIAL PRIMARY KEY,
* platform VARCHAR(20) NOT NULL,
@@ -463,12 +465,11 @@ export default app
* release_notes JSONB,
* created_at TIMESTAMP DEFAULT NOW()
* );
*
*
* 然后从数据库查询版本策略:
* const policy = await db.query(
* 'SELECT * FROM app_versions WHERE platform = $1 ORDER BY created_at DESC LIMIT 1',
* [platform]
* )
*/
```
```