refactor: 优化代码结构,添加中文注释,完善 README 文档
- Hooks/组件添加 useMemo 优化,减少不必要的重计算 - 简化 TokenUsageDashboard 的 Suspense 嵌套层级 - 完善 README: 技术栈、构建产物位置、架构说明
This commit is contained in:
77
build.ts
77
build.ts
@@ -1,11 +1,29 @@
|
||||
/**
|
||||
* 跨平台构建脚本
|
||||
*
|
||||
* 使用 Effect 框架实现类型安全的多目标编译。
|
||||
* 将 TanStack Start 的 SSR 服务器打包为独立可执行文件,
|
||||
* 用于 Tauri 的 sidecar 机制。
|
||||
*
|
||||
* 支持目标平台:
|
||||
* - Windows (x64)
|
||||
* - macOS (ARM64/x64)
|
||||
* - Linux (x64/ARM64)
|
||||
*
|
||||
* 用法: bun run build:compile
|
||||
*/
|
||||
import { Schema } from '@effect/schema'
|
||||
import { $ } from 'bun'
|
||||
import { Console, Context, Data, Effect, Layer } from 'effect'
|
||||
|
||||
// ============================================================================
|
||||
// Domain Models & Schema
|
||||
// 领域模型和 Schema 定义
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Bun 目标平台到 Rust 目标三元组的映射
|
||||
* 用于生成 Tauri sidecar 所需的文件名格式
|
||||
*/
|
||||
const targetMap = {
|
||||
'bun-windows-x64': 'x86_64-pc-windows-msvc',
|
||||
'bun-darwin-arm64': 'aarch64-apple-darwin',
|
||||
@@ -14,6 +32,7 @@ const targetMap = {
|
||||
'bun-linux-arm64': 'aarch64-unknown-linux-gnu',
|
||||
} as const
|
||||
|
||||
/** Bun 编译目标 Schema */
|
||||
const BunTargetSchema = Schema.Literal(
|
||||
'bun-windows-x64',
|
||||
'bun-darwin-arm64',
|
||||
@@ -22,48 +41,63 @@ const BunTargetSchema = Schema.Literal(
|
||||
'bun-linux-arm64',
|
||||
)
|
||||
|
||||
/** Bun 编译目标类型 */
|
||||
type BunTarget = Schema.Schema.Type<typeof BunTargetSchema>
|
||||
|
||||
/** 构建配置 Schema */
|
||||
const BuildConfigSchema = Schema.Struct({
|
||||
/** 入口文件路径 */
|
||||
entrypoint: Schema.String.pipe(Schema.nonEmptyString()),
|
||||
/** 输出目录 */
|
||||
outputDir: Schema.String.pipe(Schema.nonEmptyString()),
|
||||
/** 目标平台列表 */
|
||||
targets: Schema.Array(BunTargetSchema).pipe(Schema.minItems(1)),
|
||||
})
|
||||
|
||||
/** 构建配置类型 */
|
||||
type BuildConfig = Schema.Schema.Type<typeof BuildConfigSchema>
|
||||
|
||||
/** 构建结果 Schema */
|
||||
const BuildResultSchema = Schema.Struct({
|
||||
/** 编译目标 */
|
||||
target: BunTargetSchema,
|
||||
/** 输出文件路径列表 */
|
||||
outputs: Schema.Array(Schema.String),
|
||||
})
|
||||
|
||||
/** 构建结果类型 */
|
||||
type BuildResult = Schema.Schema.Type<typeof BuildResultSchema>
|
||||
|
||||
// ============================================================================
|
||||
// Error Models (使用 Data.TaggedError)
|
||||
// 错误模型 (使用 Effect Data.TaggedError)
|
||||
// ============================================================================
|
||||
|
||||
/** 清理目录错误 */
|
||||
class CleanError extends Data.TaggedError('CleanError')<{
|
||||
readonly dir: string
|
||||
readonly cause: unknown
|
||||
}> {}
|
||||
|
||||
/** 构建错误 */
|
||||
class BuildError extends Data.TaggedError('BuildError')<{
|
||||
readonly target: BunTarget
|
||||
readonly cause: unknown
|
||||
}> {}
|
||||
|
||||
/** 配置验证错误 */
|
||||
class ConfigError extends Data.TaggedError('ConfigError')<{
|
||||
readonly message: string
|
||||
readonly cause: unknown
|
||||
}> {}
|
||||
|
||||
// ============================================================================
|
||||
// Services
|
||||
// 服务层
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 配置服务
|
||||
* 构建配置服务
|
||||
*
|
||||
* 提供类型安全的配置验证和默认配置。
|
||||
*/
|
||||
class BuildConfigService extends Context.Tag('BuildConfigService')<
|
||||
BuildConfigService,
|
||||
@@ -71,6 +105,9 @@ class BuildConfigService extends Context.Tag('BuildConfigService')<
|
||||
>() {
|
||||
/**
|
||||
* 从原始数据创建并验证配置
|
||||
*
|
||||
* @param raw - 原始配置对象
|
||||
* @returns 验证后的配置或配置错误
|
||||
*/
|
||||
static fromRaw = (raw: unknown) =>
|
||||
Effect.gen(function* () {
|
||||
@@ -89,12 +126,13 @@ class BuildConfigService extends Context.Tag('BuildConfigService')<
|
||||
|
||||
/**
|
||||
* 默认配置 Layer
|
||||
*
|
||||
* 输出到 src-tauri/binaries 目录,供 Tauri sidecar 使用
|
||||
*/
|
||||
static readonly Live = Layer.effect(
|
||||
BuildConfigService,
|
||||
BuildConfigService.fromRaw({
|
||||
entrypoint: '.output/server/index.mjs',
|
||||
// outputDir: 'out',
|
||||
outputDir: 'src-tauri/binaries',
|
||||
targets: ['bun-windows-x64', 'bun-darwin-arm64', 'bun-linux-x64'],
|
||||
}),
|
||||
@@ -103,10 +141,13 @@ class BuildConfigService extends Context.Tag('BuildConfigService')<
|
||||
|
||||
/**
|
||||
* 文件系统服务
|
||||
*
|
||||
* 提供目录清理等文件操作。
|
||||
*/
|
||||
class FileSystemService extends Context.Tag('FileSystemService')<
|
||||
FileSystemService,
|
||||
{
|
||||
/** 清理指定目录 */
|
||||
readonly cleanDir: (dir: string) => Effect.Effect<void, CleanError>
|
||||
}
|
||||
>() {
|
||||
@@ -127,14 +168,18 @@ class FileSystemService extends Context.Tag('FileSystemService')<
|
||||
|
||||
/**
|
||||
* 构建服务
|
||||
*
|
||||
* 使用 Bun.build 进行跨平台编译。
|
||||
*/
|
||||
class BuildService extends Context.Tag('BuildService')<
|
||||
BuildService,
|
||||
{
|
||||
/** 为单个目标编译 */
|
||||
readonly buildForTarget: (
|
||||
config: BuildConfig,
|
||||
target: BunTarget,
|
||||
) => Effect.Effect<BuildResult, BuildError>
|
||||
/** 并行编译所有目标 */
|
||||
readonly buildAll: (
|
||||
config: BuildConfig,
|
||||
) => Effect.Effect<ReadonlyArray<BuildResult>, BuildError>
|
||||
@@ -172,6 +217,7 @@ class BuildService extends Context.Tag('BuildService')<
|
||||
|
||||
buildAll: (config: BuildConfig) =>
|
||||
Effect.gen(function* () {
|
||||
// 为每个目标创建编译任务
|
||||
const effects = config.targets.map((target) =>
|
||||
Effect.gen(function* () {
|
||||
yield* Console.log(`🔨 开始构建: ${target}`)
|
||||
@@ -203,6 +249,7 @@ class BuildService extends Context.Tag('BuildService')<
|
||||
} satisfies BuildResult
|
||||
}),
|
||||
)
|
||||
// 并行执行所有编译任务
|
||||
return yield* Effect.all(effects, { concurrency: 'unbounded' })
|
||||
}),
|
||||
})
|
||||
@@ -210,10 +257,13 @@ class BuildService extends Context.Tag('BuildService')<
|
||||
|
||||
/**
|
||||
* 报告服务
|
||||
*
|
||||
* 输出构建结果摘要。
|
||||
*/
|
||||
class ReporterService extends Context.Tag('ReporterService')<
|
||||
ReporterService,
|
||||
{
|
||||
/** 打印构建摘要 */
|
||||
readonly printSummary: (
|
||||
results: ReadonlyArray<BuildResult>,
|
||||
) => Effect.Effect<void>
|
||||
@@ -234,9 +284,17 @@ class ReporterService extends Context.Tag('ReporterService')<
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main Program
|
||||
// 主程序
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 构建流程主程序
|
||||
*
|
||||
* 步骤:
|
||||
* 1. 清理输出目录
|
||||
* 2. 并行构建所有目标平台
|
||||
* 3. 输出构建摘要
|
||||
*/
|
||||
const program = Effect.gen(function* () {
|
||||
const config = yield* BuildConfigService
|
||||
const fs = yield* FileSystemService
|
||||
@@ -257,9 +315,10 @@ const program = Effect.gen(function* () {
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// Layer Composition
|
||||
// Layer 组合
|
||||
// ============================================================================
|
||||
|
||||
/** 合并所有服务 Layer */
|
||||
const MainLayer = Layer.mergeAll(
|
||||
BuildConfigService.Live,
|
||||
FileSystemService.Live,
|
||||
@@ -268,9 +327,10 @@ const MainLayer = Layer.mergeAll(
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Runner
|
||||
// 执行入口
|
||||
// ============================================================================
|
||||
|
||||
/** 可运行的程序(附带错误处理) */
|
||||
const runnable = program.pipe(
|
||||
Effect.provide(MainLayer),
|
||||
Effect.catchTags({
|
||||
@@ -284,6 +344,7 @@ const runnable = program.pipe(
|
||||
Effect.tapErrorCause((cause) => Console.error('❌ 未预期的错误:', cause)),
|
||||
)
|
||||
|
||||
// 执行程序
|
||||
Effect.runPromise(runnable).catch(() => {
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user