diff --git a/docs/technical/README.md b/docs/technical/README.md index 5153be57..de04317f 100644 --- a/docs/technical/README.md +++ b/docs/technical/README.md @@ -9,6 +9,7 @@ - [MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md](./MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md):冻结抓大鹅 Match3D B1+B2 的纯领域规则 crate、Rust/TypeScript shared contracts,以及 Stage1 不触碰 SpacetimeDB 表和 api-server 的边界。 - [MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md](./MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md):记录抓大鹅 F1 创作入口、Agent 工作区、参考图入口、本地 mock client 与后续 B5 HTTP facade 替换点。 - [MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md](./MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md):冻结抓大鹅 F2 结果页、基础信息编辑、发布前试玩入口、发布门槛、自动保存和已发布作品二次编辑恢复口径。 +- [MATCH3D_SPACETIME_CLIENT_AND_API_FACADE_2026-04-30.md](./MATCH3D_SPACETIME_CLIENT_AND_API_FACADE_2026-04-30.md):记录抓大鹅 B4+B5 已落地的 SpacetimeDB bindings、`spacetime-client` facade、`api-server` HTTP 路由、shared contract 对齐和验收命令。 - [PLATFORM_MOBILE_BOTTOM_DOCK_VIEWPORT_FIX_2026-04-30.md](./PLATFORM_MOBILE_BOTTOM_DOCK_VIEWPORT_FIX_2026-04-30.md):记录平台首页底部 dock 在手机浏览器地址栏展开时脱离可见区域的根因,以及 `100dvh`、固定底部锚点和安全区占位的修复口径。 - [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md):记录 SpacetimeDB private 表迁移 JSON 导出/导入 procedure、迁移操作员授权、HTTP 413 分片导入、Jenkins 自动迁移回灌和导入脚本参数。 - [JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md](./JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md):记录 `Genarrative-Database-Export` / `Genarrative-Database-Import` 两条 SCM-backed 数据库迁移流水线参数、默认 dry-run、token 边界和 `CHUNK_SIZE` 413 规避参数。 diff --git a/server-rs/crates/api-server/src/match3d.rs b/server-rs/crates/api-server/src/match3d.rs index 5b0087f3..cf6762e3 100644 --- a/server-rs/crates/api-server/src/match3d.rs +++ b/server-rs/crates/api-server/src/match3d.rs @@ -21,10 +21,9 @@ use serde_json::{Value, json}; use shared_contracts::{ match3d_agent::{ CreateMatch3DAgentSessionRequest, ExecuteMatch3DAgentActionRequest, - Match3DAgentActionResponse, Match3DAgentMessageResponse, - Match3DAgentSessionResponse, Match3DAgentSessionSnapshotResponse, - Match3DAnchorItemResponse, Match3DAnchorPackResponse, Match3DCreatorConfigResponse, - Match3DResultDraftResponse, SendMatch3DAgentMessageRequest, + Match3DAgentActionResponse, Match3DAgentMessageResponse, Match3DAgentSessionResponse, + Match3DAgentSessionSnapshotResponse, Match3DAnchorItemResponse, Match3DAnchorPackResponse, + Match3DCreatorConfigResponse, Match3DResultDraftResponse, SendMatch3DAgentMessageRequest, }, match3d_runtime::{ ClickMatch3DItemRequest, Match3DClickConfirmationResponse, Match3DClickResponse, @@ -41,12 +40,11 @@ use spacetime_client::{ Match3DAgentMessageFinalizeRecordInput, Match3DAgentMessageRecord, Match3DAgentMessageSubmitRecordInput, Match3DAgentSessionCreateRecordInput, Match3DAgentSessionRecord, Match3DAnchorItemRecord, Match3DAnchorPackRecord, - Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, - Match3DCreatorConfigRecord, Match3DItemSnapshotRecord, Match3DResultDraftRecord, - Match3DRunClickRecordInput, Match3DRunRecord, Match3DRunRestartRecordInput, - Match3DRunStartRecordInput, Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, - Match3DTraySlotRecord, Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput, - SpacetimeClientError, + Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, Match3DCreatorConfigRecord, + Match3DItemSnapshotRecord, Match3DResultDraftRecord, Match3DRunClickRecordInput, + Match3DRunRecord, Match3DRunRestartRecordInput, Match3DRunStartRecordInput, + Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, Match3DTraySlotRecord, + Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput, SpacetimeClientError, }; use crate::{ @@ -938,7 +936,11 @@ fn map_match3d_run_response(run: Match3DRunRecord) -> Match3DRunSnapshotResponse clear_count: run.clear_count, total_item_count: run.total_item_count, cleared_item_count: run.cleared_item_count, - items: run.items.into_iter().map(map_match3d_item_response).collect(), + items: run + .items + .into_iter() + .map(map_match3d_item_response) + .collect(), tray_slots: run .tray_slots .into_iter() @@ -1002,7 +1004,10 @@ fn build_config_from_create_request( .unwrap_or(MATCH3D_DEFAULT_THEME) .to_string(), reference_image_src: payload.reference_image_src.clone(), - clear_count: payload.clear_count.unwrap_or(MATCH3D_DEFAULT_CLEAR_COUNT).max(1), + clear_count: payload + .clear_count + .unwrap_or(MATCH3D_DEFAULT_CLEAR_COUNT) + .max(1), difficulty: payload .difficulty .unwrap_or(MATCH3D_DEFAULT_DIFFICULTY) @@ -1251,7 +1256,11 @@ fn match3d_json( }) } -fn match3d_bad_request(request_context: &RequestContext, provider: &str, message: &str) -> Response { +fn match3d_bad_request( + request_context: &RequestContext, + provider: &str, + message: &str, +) -> Response { match3d_error_response( request_context, provider, @@ -1317,9 +1326,7 @@ fn match3d_sse_json_event(event_name: &str, payload: Value) -> Result Event { match match3d_sse_json_event(event_name, payload) { Ok(event) => event, - Err(error) => Event::default() - .event("error") - .data(format!("{error:?}")), + Err(error) => Event::default().event("error").data(format!("{error:?}")), } } diff --git a/server-rs/crates/api-server/src/puzzle.rs b/server-rs/crates/api-server/src/puzzle.rs index 3a4e3d20..3474b9d7 100644 --- a/server-rs/crates/api-server/src/puzzle.rs +++ b/server-rs/crates/api-server/src/puzzle.rs @@ -36,11 +36,11 @@ use shared_contracts::{ }, puzzle_gallery::{PuzzleGalleryDetailResponse, PuzzleGalleryResponse}, puzzle_runtime::{ - AdvanceLocalPuzzleNextLevelRequest, PuzzleBoardSnapshotResponse, PuzzleCellPositionResponse, - PuzzleLeaderboardEntryResponse, PuzzleMergedGroupStateResponse, PuzzlePieceStateResponse, - PuzzleRunResponse, PuzzleRunSnapshotResponse, PuzzleRuntimeLevelSnapshotResponse, - StartPuzzleRunRequest, SubmitPuzzleLeaderboardRequest, SwapPuzzlePiecesRequest, - UpdatePuzzleRuntimePauseRequest, UsePuzzleRuntimePropRequest, + AdvanceLocalPuzzleNextLevelRequest, PuzzleBoardSnapshotResponse, + PuzzleCellPositionResponse, PuzzleLeaderboardEntryResponse, PuzzleMergedGroupStateResponse, + PuzzlePieceStateResponse, PuzzleRunResponse, PuzzleRunSnapshotResponse, + PuzzleRuntimeLevelSnapshotResponse, StartPuzzleRunRequest, SubmitPuzzleLeaderboardRequest, + SwapPuzzlePiecesRequest, UpdatePuzzleRuntimePauseRequest, UsePuzzleRuntimePropRequest, }, puzzle_works::{ PutPuzzleWorkRequest, PuzzleWorkDetailResponse, PuzzleWorkMutationResponse, @@ -57,10 +57,10 @@ use spacetime_client::{ PuzzleLeaderboardEntryRecord, PuzzleLeaderboardSubmitRecordInput, PuzzleMergedGroupRecord, PuzzlePieceStateRecord, PuzzlePublishRecordInput, PuzzleResultDraftRecord, PuzzleResultPreviewBlockerRecord, PuzzleResultPreviewFindingRecord, PuzzleResultPreviewRecord, - PuzzleRunPauseRecordInput, PuzzleRunPropRecordInput, PuzzleRunRecord, PuzzleRunStartRecordInput, - PuzzleRunSwapRecordInput, PuzzleRuntimeLevelRecord, PuzzleSelectCoverImageRecordInput, - PuzzleWorkProfileRecord, PuzzleWorkRemixRecordInput, PuzzleWorkUpsertRecordInput, - SpacetimeClientError, + PuzzleRunPauseRecordInput, PuzzleRunPropRecordInput, PuzzleRunRecord, + PuzzleRunStartRecordInput, PuzzleRunSwapRecordInput, PuzzleRuntimeLevelRecord, + PuzzleSelectCoverImageRecordInput, PuzzleWorkProfileRecord, PuzzleWorkRemixRecordInput, + PuzzleWorkUpsertRecordInput, SpacetimeClientError, }; use std::convert::Infallible; use tokio::time::sleep; diff --git a/server-rs/crates/spacetime-client/src/lib.rs b/server-rs/crates/spacetime-client/src/lib.rs index 54ace678..9e6c65ab 100644 --- a/server-rs/crates/spacetime-client/src/lib.rs +++ b/server-rs/crates/spacetime-client/src/lib.rs @@ -24,15 +24,15 @@ pub use mapper::{ CustomWorldProfileUpsertRecordInput, CustomWorldPublishGateRecord, CustomWorldPublishWorldRecord, CustomWorldPublishWorldRecordInput, CustomWorldPublishedProfileCompileRecord, CustomWorldResultPreviewBlockerRecord, - CustomWorldSupportedActionRecord, CustomWorldWorkSummaryRecord, NpcBattleInteractionRecord, + CustomWorldSupportedActionRecord, CustomWorldWorkSummaryRecord, Match3DAgentMessageFinalizeRecordInput, Match3DAgentMessageRecord, Match3DAgentMessageSubmitRecordInput, Match3DAgentSessionCreateRecordInput, Match3DAgentSessionRecord, Match3DAnchorItemRecord, Match3DAnchorPackRecord, - Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, - Match3DCreatorConfigRecord, Match3DItemSnapshotRecord, Match3DResultDraftRecord, - Match3DRunClickRecordInput, Match3DRunRecord, Match3DRunRestartRecordInput, - Match3DRunStartRecordInput, Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, - Match3DTraySlotRecord, Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput, + Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, Match3DCreatorConfigRecord, + Match3DItemSnapshotRecord, Match3DResultDraftRecord, Match3DRunClickRecordInput, + Match3DRunRecord, Match3DRunRestartRecordInput, Match3DRunStartRecordInput, + Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, Match3DTraySlotRecord, + Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput, NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord, PuzzleAgentMessageFinalizeRecordInput, PuzzleAgentMessageRecord, PuzzleAgentMessageSubmitRecordInput, PuzzleAgentSessionCreateRecordInput, PuzzleAgentSessionRecord, diff --git a/server-rs/crates/spacetime-client/src/mapper.rs b/server-rs/crates/spacetime-client/src/mapper.rs index 2760ddaf..99f835e6 100644 --- a/server-rs/crates/spacetime-client/src/mapper.rs +++ b/server-rs/crates/spacetime-client/src/mapper.rs @@ -1404,8 +1404,8 @@ pub(crate) fn map_match3d_agent_session_procedure_result( "SpacetimeDB procedure 未返回 match3d agent session 快照".to_string(), ) })?; - let session = serde_json::from_str::(&session_json) - .map_err(|error| { + let session = + serde_json::from_str::(&session_json).map_err(|error| { SpacetimeClientError::Runtime(format!("match3d session_json 非法: {error}")) })?; @@ -1424,7 +1424,9 @@ pub(crate) fn map_match3d_work_procedure_result( } let work_json = result.work_json.ok_or_else(|| { - SpacetimeClientError::Procedure("SpacetimeDB procedure 未返回 match3d work 快照".to_string()) + SpacetimeClientError::Procedure( + "SpacetimeDB procedure 未返回 match3d work 快照".to_string(), + ) })?; let work = serde_json::from_str::(&work_json).map_err(|error| { SpacetimeClientError::Runtime(format!("match3d work_json 非法: {error}")) @@ -1449,8 +1451,8 @@ pub(crate) fn map_match3d_works_procedure_result( "SpacetimeDB procedure 未返回 match3d works 快照".to_string(), ) })?; - let items = serde_json::from_str::>(&items_json) - .map_err(|error| { + let items = + serde_json::from_str::>(&items_json).map_err(|error| { SpacetimeClientError::Runtime(format!("match3d works items_json 非法: {error}")) })?; @@ -2519,9 +2521,7 @@ fn map_match3d_agent_message_snapshot( } } -fn map_match3d_work_snapshot( - snapshot: Match3DWorkJsonRecord, -) -> Match3DWorkProfileRecord { +fn map_match3d_work_snapshot(snapshot: Match3DWorkJsonRecord) -> Match3DWorkProfileRecord { let config = map_match3d_creator_config(snapshot.config); Match3DWorkProfileRecord { work_id: snapshot.profile_id.clone(), @@ -2566,7 +2566,9 @@ fn map_match3d_run_snapshot(snapshot: Match3DRunJsonRecord) -> Match3DRunRecord .map(|item| { let tray_slot_index = tray_slots .iter() - .find(|slot| slot.item_instance_id.as_deref() == Some(item.item_instance_id.as_str())) + .find(|slot| { + slot.item_instance_id.as_deref() == Some(item.item_instance_id.as_str()) + }) .map(|slot| slot.slot_index); map_match3d_item_snapshot(item, tray_slot_index) }) @@ -2610,9 +2612,7 @@ fn map_match3d_item_snapshot( } } -fn map_match3d_tray_slot_snapshot( - snapshot: Match3DTraySlotJsonRecord, -) -> Match3DTraySlotRecord { +fn map_match3d_tray_slot_snapshot(snapshot: Match3DTraySlotJsonRecord) -> Match3DTraySlotRecord { Match3DTraySlotRecord { slot_index: snapshot.slot_index, item_instance_id: snapshot.item_instance_id, @@ -2626,16 +2626,8 @@ fn build_match3d_anchor_pack(config: &Match3DCreatorConfigRecord) -> Match3DAnch let difficulty = config.difficulty.to_string(); Match3DAnchorPackRecord { theme: build_match3d_anchor_item("theme", "题材主题", config.theme_text.as_str()), - clear_count: build_match3d_anchor_item( - "clearCount", - "需要消除次数", - clear_count.as_str(), - ), - difficulty: build_match3d_anchor_item( - "difficulty", - "难度", - difficulty.as_str(), - ), + clear_count: build_match3d_anchor_item("clearCount", "需要消除次数", clear_count.as_str()), + difficulty: build_match3d_anchor_item("difficulty", "难度", difficulty.as_str()), } } diff --git a/server-rs/crates/spacetime-client/src/match3d.rs b/server-rs/crates/spacetime-client/src/match3d.rs index 97c8b004..32db7478 100644 --- a/server-rs/crates/spacetime-client/src/match3d.rs +++ b/server-rs/crates/spacetime-client/src/match3d.rs @@ -298,9 +298,9 @@ impl SpacetimeClient { }; self.call_after_connect(move |connection, sender| { - connection.procedures().start_match_3_d_run_then( - procedure_input, - move |_, result| { + connection + .procedures() + .start_match_3_d_run_then(procedure_input, move |_, result| { let mapped = result .map_err(|error| SpacetimeClientError::Procedure(error.to_string())) .and_then(map_match3d_run_procedure_result) @@ -309,8 +309,7 @@ impl SpacetimeClient { run }); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -321,12 +320,15 @@ impl SpacetimeClient { owner_user_id: String, ) -> Result { let procedure_owner_user_id = owner_user_id.clone(); - let procedure_input = Match3DRunGetInput { run_id, owner_user_id }; + let procedure_input = Match3DRunGetInput { + run_id, + owner_user_id, + }; self.call_after_connect(move |connection, sender| { - connection.procedures().get_match_3_d_run_then( - procedure_input, - move |_, result| { + connection + .procedures() + .get_match_3_d_run_then(procedure_input, move |_, result| { let mapped = result .map_err(|error| SpacetimeClientError::Procedure(error.to_string())) .and_then(map_match3d_run_procedure_result) @@ -335,8 +337,7 @@ impl SpacetimeClient { run }); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -357,9 +358,9 @@ impl SpacetimeClient { }; self.call_after_connect(move |connection, sender| { - connection.procedures().click_match_3_d_item_then( - procedure_input, - move |_, result| { + connection + .procedures() + .click_match_3_d_item_then(procedure_input, move |_, result| { let mapped = result .map_err(|error| SpacetimeClientError::Procedure(error.to_string())) .and_then(map_match3d_click_item_procedure_result) @@ -371,8 +372,7 @@ impl SpacetimeClient { confirmation }); send_once(&sender, mapped); - }, - ); + }); }) .await } @@ -389,9 +389,9 @@ impl SpacetimeClient { }; self.call_after_connect(move |connection, sender| { - connection.procedures().stop_match_3_d_run_then( - procedure_input, - move |_, result| { + connection + .procedures() + .stop_match_3_d_run_then(procedure_input, move |_, result| { let mapped = result .map_err(|error| SpacetimeClientError::Procedure(error.to_string())) .and_then(map_match3d_run_procedure_result) @@ -400,8 +400,7 @@ impl SpacetimeClient { run }); send_once(&sender, mapped); - }, - ); + }); }) .await }