feat(游戏共创): 共创主题(二)公开读路径(事务 + client + 两个公开路由 + 详情 themes 增量)
Project CI / AI game creator shell Rust crates (pull_request) Successful in 5m44s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m35s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m37s
Project CI / Backend tests (pull_request) Successful in 9m29s
Project CI / Frontend tests (pull_request) Successful in 3m7s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m7s
Project CI / Repository checks (pull_request) Successful in 6m48s
Project CI / Native shell tests (pull_request) Successful in 8m39s

- **事务**(`spacetime-module`):公共列表 `list_game_distribution_themes_tx`(匿名可读;先按 `published` 过滤、再排序切页——`created_at` 倒序 + `theme_id` 兜底;只对当页现算 `member_count`;不写库);主题详情 `get_game_distribution_theme_detail_tx`(不存在 / 未发布**同一句**「主题不存在」→ 404;`roots` 逐条复用公开目录同一份 `public_game_distribution_snapshot`;成员可见性委托 `game_distribution_theme_member_visible`,被滤掉的行**不删除**;已发布但可见成员为空 = Ok + 空 roots = 200);作品→主题 `list_game_distribution_theme_refs_for_root_tx`(入参任意代作品,先取**根**再按根反查成员、只保留 `published` 主题;排序复用 `sort_public_themes`)。**根解析只有一份实现**:抽成 `game_distribution_theme_root_of` 并让既有 `game_distribution_lineage_tx` 复用(测试钉住)。
- **client**:3 个新方法 + mapper 记录类型(`spacetime-client`)。
- **公开路由**(`api-server`):`GET /api/game-distribution/themes?limit=&cursor=`(匿名可读 + `no-store`;`limit` 缺省 20 / 上限 50 / 超界截断;非法游标 **400** 透传;末页 `nextCursor: null`)、`GET /api/game-distribution/themes/{theme_id}`(顶层扁平 `{themeId,name,summary,badge,memberCount,roots}`;不存在 / draft / archived → **404**,不回空壳、不带 `THEME_` 码)、既有公开作品详情追加 `themes`(匿名与登录**都**发、空数组恒发;`collected` 仅登录发的老口径不变;因按根反查,**第 N 代作品也能跳到主题页**)。
- **错误码**:新增 6 个 `THEME_*` 稳定码集中在 `map_spacetime_error` 映射(不落 axum 默认 422 纯文本);未登记码兜底 **400 `THEME_ERROR`**。
- **契约/parity**:5 条手拼响应构建器登记(`public_themes_payload` / `public_theme_detail_payload` / `public_theme_summary_payload` / `theme_reference_payload`,并给 `public_game_detail_payload` 加 `mustEmit: [themes]`)→ 58 组类型 + 10 个构建器一致。
- **测试 +13**:spacetime-module 4 条源码结构断言(根解析单一实现、先过滤再切页、投影不删行、详情只有两种失败且同一 404 文案、refs 走具名根索引 + 只保留 published)、api-server 7 条(路由挂载与 `no-store`、列表/详情响应形状与末页 null、`roots` 逐字节等于 `public_game_payload`、limit 缺省与截断、非法游标 400、404 与 6 个 THEME_ 码映射、作品详情 `themes` 恒发而 `collected` 仅登录)、client mapper 2 条。
- **门禁**:wasm build 0;`cargo check --all-targets` 0;`cargo test -p api-server game_distribution` **79 passed**;`cargo test -p module-game-distribution` **97 passed**;`cargo test -p spacetime-module` **278 passed** / 1 ignored;`cargo test -p spacetime-client` 34 passed;DTO parity **58 组 / 10 构建器**;`check:spacetime-schema` 0(96 tables);`check:encoding` 0(5399 files);`cargo fmt --all -- --check` 0;`git diff --check` 0。

已知限制(**已上报,待拍板**):主题详情的 `roots` 沿用页上限 50,`memberCount == roots.len()`,因此可见成员 > 50 时**静默截断且无「还有更多」标志**——设计文档未定义该行为,三个备选(去上限 / 加成员游标 / memberCount 报真实数)待定;本轮不改契约。
This commit is contained in:
2026-10-06 02:15:03 +08:00
parent 2fa201e0dc
commit 742723a58c
19 changed files with 1831 additions and 30 deletions
@@ -158,6 +158,9 @@ const RESPONSE_BUILDERS = [
fn: 'public_game_detail_payload',
ts: 'GameDistributionGame',
base: 'public_game_payload',
// `themes` 与 `collected` 相反:**匿名与登录都发**(主题入口是公开页的一部分,不是 per-user
// 数据),没有所属主题时发空数组而不是缺键,因此它必须进 mustEmit。
mustEmit: ['themes'],
},
{ fn: 'private_version_payload', ts: 'GameDistributionPrivateVersion' },
{ fn: 'version_summary_payload', ts: 'GameDistributionVersionSummary' },
@@ -168,6 +171,34 @@ const RESPONSE_BUILDERS = [
ts: 'GameDistributionMyCollectionsResponse',
mustEmit: ['games', 'nextCursor'],
},
{
// 公开共创主题列表:`themes` / `nextCursor` 两个键都必须发出(末页 `nextCursor: null`)。
// 单条的形状由 `public_theme_summary_payload` 拼,这里只证明顶层键与 TS 契约一致。
fn: 'public_themes_payload',
ts: 'GameDistributionThemeListResponse',
mustEmit: ['themes', 'nextCursor'],
},
{
// 公开共创主题详情:顶层扁平(与 `GET /games/{gameId}` 同形),六个键都由这一条路径发出。
// `roots` 逐条复用公开目录同一份 `public_game_payload`(不是第二套作品摘要)。
fn: 'public_theme_detail_payload',
ts: 'GameDistributionThemeDetail',
mustEmit: ['themeId', 'name', 'summary', 'badge', 'memberCount', 'roots'],
},
{
// 主题条目(列表单条与详情头部共用):`public_themes_payload` 里逐条调用它,`roots` 之外
// 的嵌套对象在顶层键解析里看不到,所以单独登记,让「条目到底发哪几个键」有独立证据。
fn: 'public_theme_summary_payload',
ts: 'GameDistributionThemeSummary',
mustEmit: ['themeId', 'name', 'summary', 'badge', 'memberCount'],
},
{
// 作品详情 `themes` 增量的单条:`{ themeId, name, badge }`(不含简介与成员数——那是主题页的事)。
// 它是**数组元素**,顶层键解析抓不到它,因此单独登记,让这条增量条目的形状也有证据。
fn: 'theme_reference_payload',
ts: 'GameDistributionThemeReference',
mustEmit: ['themeId', 'name', 'badge'],
},
];
function camelCase(value) {
File diff suppressed because it is too large Load Diff
@@ -33,6 +33,24 @@ pub const GAME_DISTRIBUTION_VERSION_NUMBER_CONFLICT: &str = "VERSION_NUMBER_CONF
pub const GAME_DISTRIBUTION_COLLECTION_STATE_CONFLICT: &str =
"作品状态不允许收藏(未公开或已软删除)";
/// 共创主题相关错误的稳定前缀码(`模块前缀_原因`,与 `FORK_*` 同族写法)。
///
/// 领域侧(`spacetime-module`)与 api-server 的集中映射**共用这些常量**:新增一种主题错误只需
/// 在这里加一个码并在映射表里加一行,不会出现「事务里写了一个没人认识的字符串」这种静默漂移。
/// 公开侧刻意**不带**这些码:主题不存在 / 未发布一律只回「主题不存在」文案(不确认未发布主题的
/// 存在性),因此公开的 404 与这里的 `THEME_NOT_FOUND` 是两条不同的路径。
pub const GAME_DISTRIBUTION_THEME_NOT_FOUND: &str = "THEME_NOT_FOUND";
/// 后台请求参数非法:空 `name` / 非法 `status`(含列表过滤值)。
pub const GAME_DISTRIBUTION_THEME_BAD_REQUEST: &str = "THEME_BAD_REQUEST";
/// 主题列表游标格式非法。
pub const GAME_DISTRIBUTION_THEME_INVALID_CURSOR: &str = "THEME_INVALID_CURSOR";
/// 同 `Idempotency-Key` 不同请求摘要。
pub const GAME_DISTRIBUTION_THEME_IDEMPOTENCY_CONFLICT: &str = "THEME_IDEMPOTENCY_CONFLICT";
/// 目标作品有血缘行(非根),不能作为主题成员。
pub const GAME_DISTRIBUTION_THEME_MEMBER_NOT_ROOT: &str = "THEME_MEMBER_NOT_ROOT";
/// 目标作品不存在。
pub const GAME_DISTRIBUTION_THEME_MEMBER_GAME_NOT_FOUND: &str = "THEME_MEMBER_GAME_NOT_FOUND";
/// 发布页免费生成简介与分类的输入。
///
/// 只传经过裁剪的项目摘要,不传本地绝对路径、聊天记录、凭据或完整 manifest。
@@ -105,8 +105,10 @@ pub use self::game_distribution::{
GameDistributionPublicGameRecord, GameDistributionRatingSummaryRecord,
GameDistributionReviewGameListRecord, GameDistributionReviewGameRecord,
GameDistributionReviewModerationOperationRecord, GameDistributionReviewModerationRecord,
GameDistributionUserReviewListRecord, GameDistributionUserReviewRecord,
GameDistributionUserReviewSaveRecord, GameDistributionVersionRecord,
GameDistributionThemeDetailRecord, GameDistributionThemeReferenceRecord,
GameDistributionThemeSummaryRecord, GameDistributionUserReviewListRecord,
GameDistributionUserReviewRecord, GameDistributionUserReviewSaveRecord,
GameDistributionVersionRecord,
};
pub use self::llm_router_account::{LlmRouterAccountRecord, LlmRouterAccountUpsertRecordInput};
pub use self::payment::{
@@ -177,8 +179,9 @@ pub(crate) use self::game_distribution::{
map_game_distribution_fork_source_result, map_game_distribution_game_result,
map_game_distribution_lineage_result, map_game_distribution_owner_game_list_result,
map_game_distribution_public_game_list_result, map_game_distribution_public_game_result,
map_game_distribution_review_list_result, map_game_distribution_version_result,
map_review_moderation_operation, map_user_review,
map_game_distribution_review_list_result, map_game_distribution_theme_detail_result,
map_game_distribution_theme_list_result, map_game_distribution_theme_refs_result,
map_game_distribution_version_result, map_review_moderation_operation, map_user_review,
};
pub(crate) use self::payment::{
map_payment_api_key_list_result, map_payment_api_key_result, map_payment_app_list_result,
@@ -351,6 +351,40 @@ pub struct GameDistributionCollectionMutationRecord {
pub replayed: bool,
}
/// 公开共创主题的对外投影:列表条目与详情头部**共用同一个形状**。
///
/// `member_count` 是**当前公开可见成员数**(与详情 `roots` 长度同一个数),不是成员行总数。
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct GameDistributionThemeSummaryRecord {
pub theme_id: String,
pub name: String,
pub summary: String,
pub badge: String,
pub member_count: u64,
}
/// 作品详情 `themes` 增量的单个条目:只够渲染一个跳转入口(不含简介与成员数)。
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct GameDistributionThemeReferenceRecord {
pub theme_id: String,
pub name: String,
pub badge: String,
}
/// 公开共创主题详情:主题头 + 可见成员根(逐条公开目录同一份公开投影)。
///
/// 主题不存在 / 未发布时模块侧 `ok == false`,这里折成 `Procedure` 错误,由 api-server 的既有
/// 映射落 404(不返回空壳);已发布但可见成员为空是**正常**结果(空 `roots`)。
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct GameDistributionThemeDetailRecord {
pub theme_id: String,
pub name: String,
pub summary: String,
pub badge: String,
pub member_count: u64,
pub roots: Vec<GameDistributionPublicGameRecord>,
}
fn map_game(
value: crate::module_bindings::GameDistributionGameSnapshot,
) -> GameDistributionGameRecord {
@@ -596,6 +630,73 @@ fn map_public_game(
}
}
/// 公开主题的对外投影(列表条目与详情头部共用同一个形状)。
fn map_theme(
value: crate::module_bindings::GameDistributionThemeSnapshot,
) -> GameDistributionThemeSummaryRecord {
GameDistributionThemeSummaryRecord {
theme_id: value.theme_id,
name: value.name,
summary: value.summary,
badge: value.badge,
member_count: value.member_count,
}
}
/// 作品详情 `themes` 增量的单个条目。
fn map_theme_reference(
value: crate::module_bindings::GameDistributionThemeReferenceSnapshot,
) -> GameDistributionThemeReferenceRecord {
GameDistributionThemeReferenceRecord {
theme_id: value.theme_id,
name: value.name,
badge: value.badge,
}
}
/// 公开主题列表:`ok == false` 是服务端失败(游标非法等,走既有错误映射 → 400)。
///
/// 同时透传真实的下页游标(`None` = 最后一页),让 api-server 能原样发出 `nextCursor`。
pub(crate) fn map_game_distribution_theme_list_result(
result: crate::module_bindings::GameDistributionThemeListResult,
) -> Result<(Vec<GameDistributionThemeSummaryRecord>, Option<String>), SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok((
result.themes.into_iter().map(map_theme).collect(),
result.next_cursor,
))
}
/// 公开主题详情:`ok == false` 表示主题不存在 / 未发布,折成 `Procedure` 错误由 api-server 映射
/// 404(这里**不**构造空壳主题,否则「不存在」会被渲染成一个空白的正常主题页)。
pub(crate) fn map_game_distribution_theme_detail_result(
result: crate::module_bindings::GameDistributionThemeDetailResult,
) -> Result<GameDistributionThemeDetailRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(GameDistributionThemeDetailRecord {
theme_id: result.theme_id,
name: result.name,
summary: result.summary,
badge: result.badge,
member_count: result.member_count,
roots: result.roots.into_iter().map(map_public_game).collect(),
})
}
/// 作品详情 `themes` 增量:没有所属主题时是空数组(不是错误,也不是 `None`)。
pub(crate) fn map_game_distribution_theme_refs_result(
result: crate::module_bindings::GameDistributionThemeRefsResult,
) -> Result<Vec<GameDistributionThemeReferenceRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result.themes.into_iter().map(map_theme_reference).collect())
}
pub(crate) fn map_game_distribution_admin_game_list_result(
result: crate::module_bindings::GameDistributionAdminGameListResult,
) -> Result<(Vec<GameDistributionAdminGameRecord>, Option<String>), SpacetimeClientError> {
@@ -738,3 +839,79 @@ mod lineage_result_tests {
assert!(derived.truncated);
}
}
/// 主题相关结果的映射:失败必须折成 `Procedure` 错误(api-server 才能映射 404 / 400),
/// **不能**折成空壳主题或空列表——空壳会把「主题不存在」渲染成「主题存在但没有内容」,
/// 而这正是公开详情那条 404 纪律要避免的。`ok = true` + 空 `roots` 则是正常结果(空态)。
#[cfg(test)]
mod theme_result_tests {
use super::*;
fn detail_result(ok: bool) -> crate::module_bindings::GameDistributionThemeDetailResult {
crate::module_bindings::GameDistributionThemeDetailResult {
ok,
theme_id: if ok { "theme_a" } else { "" }.to_string(),
name: if ok { "主题 theme_a" } else { "" }.to_string(),
summary: if ok { "运营简介" } else { "" }.to_string(),
badge: if ok { "精选" } else { "" }.to_string(),
member_count: if ok { 1 } else { 0 },
roots: Vec::new(),
error_message: (!ok).then(|| "主题不存在".to_string()),
}
}
#[test]
fn theme_not_found_maps_to_procedure_error_instead_of_an_empty_theme() {
let error = map_game_distribution_theme_detail_result(detail_result(false))
.expect_err("ok = false 必须是错误");
assert_eq!(error.to_string(), "主题不存在");
let detail = map_game_distribution_theme_detail_result(detail_result(true))
.expect("已发布主题(哪怕可见成员为空)是正常结果");
assert_eq!(detail.theme_id, "theme_a");
assert_eq!(detail.member_count, 1);
assert!(detail.roots.is_empty(), "空成员不是错误");
}
#[test]
fn theme_list_keeps_the_real_cursor_and_refs_map_to_an_empty_array() {
let (themes, next_cursor) = map_game_distribution_theme_list_result(
crate::module_bindings::GameDistributionThemeListResult {
ok: true,
themes: vec![crate::module_bindings::GameDistributionThemeSnapshot {
theme_id: "theme_a".to_string(),
name: "主题 theme_a".to_string(),
summary: "运营简介".to_string(),
badge: "精选".to_string(),
member_count: 3,
}],
next_cursor: Some("100:theme_a".to_string()),
error_message: None,
},
)
.expect("列表结果");
assert_eq!(themes.len(), 1);
assert_eq!(themes[0].member_count, 3);
assert_eq!(next_cursor.as_deref(), Some("100:theme_a"));
let refs = map_game_distribution_theme_refs_result(
crate::module_bindings::GameDistributionThemeRefsResult {
ok: true,
themes: Vec::new(),
error_message: None,
},
)
.expect("增量结果");
assert!(refs.is_empty(), "没有所属主题是空数组,不是错误");
let list_error = map_game_distribution_theme_list_result(
crate::module_bindings::GameDistributionThemeListResult {
ok: false,
themes: Vec::new(),
next_cursor: None,
error_message: Some("主题列表游标格式无效".to_string()),
},
)
.expect_err("非法游标必须是错误(api-server 才能映射 400)");
assert_eq!(list_error.to_string(), "主题列表游标格式无效");
}
}
@@ -841,6 +841,86 @@ impl SpacetimeClient {
.await
}
/// 公开共创主题列表(游标分页);只含 `published` 主题。
///
/// 返回 `(themes, next_cursor)`:`next_cursor` 为 `None` 表示这一页就是最后一页。
/// 游标格式非法由模块侧报错,api-server 透传成 400(不吞掉、也不自己造一种 200 的空页)。
pub async fn list_game_distribution_themes(
&self,
limit: u32,
cursor: Option<String>,
) -> Result<(Vec<GameDistributionThemeSummaryRecord>, Option<String>), SpacetimeClientError>
{
let input = crate::module_bindings::GameDistributionThemeListInput { limit, cursor };
self.call_after_connect(
"list_game_distribution_themes",
move |connection, sender| {
connection
.procedures()
.list_game_distribution_themes_and_return_then(input, move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(map_game_distribution_theme_list_result);
send_once(&sender, mapped);
});
},
)
.await
}
/// 公开共创主题详情:主题头 + 可见成员根(逐条公开目录同一份公开投影)。
///
/// 主题不存在 / 未发布时模块侧 `ok == false`,这里折成 `Procedure` 错误,由 api-server 的
/// 既有映射落 404(不返回空壳主题);已发布但可见成员为空是正常结果(空 `roots`)。
pub async fn get_game_distribution_theme_detail(
&self,
theme_id: String,
) -> Result<GameDistributionThemeDetailRecord, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionThemeDetailInput { theme_id };
self.call_after_connect(
"get_game_distribution_theme_detail",
move |connection, sender| {
connection
.procedures()
.get_game_distribution_theme_detail_and_return_then(input, move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(map_game_distribution_theme_detail_result);
send_once(&sender, mapped);
});
},
)
.await
}
/// 某作品所属的公开共创主题(作品详情 `themes` 增量)。
///
/// 入参是**作品** ID(任意代):根解析在事务内用血缘行完成,因此第 N 代作品也能拿到它所属根
/// 的主题。没有所属主题时是空数组,不是错误。
pub async fn list_game_distribution_theme_refs_for_root(
&self,
game_id: String,
) -> Result<Vec<GameDistributionThemeReferenceRecord>, SpacetimeClientError> {
let input = crate::module_bindings::GameDistributionThemeRefsInput { game_id };
self.call_after_connect(
"list_game_distribution_theme_refs_for_root",
move |connection, sender| {
connection
.procedures()
.list_game_distribution_theme_refs_for_root_and_return_then(
input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(map_game_distribution_theme_refs_result);
send_once(&sender, mapped);
},
);
},
)
.await
}
/// 批量累加已公开游戏的游玩次数;非公开游戏由事务静默跳过。
pub async fn increment_game_distribution_game_play_counts(
&self,
@@ -487,8 +487,16 @@ pub mod game_distribution_review_type;
pub mod game_distribution_set_fork_authorization_input_type;
pub mod game_distribution_submit_review_input_type;
pub mod game_distribution_suspend_input_type;
pub mod game_distribution_theme_detail_input_type;
pub mod game_distribution_theme_detail_result_type;
pub mod game_distribution_theme_list_input_type;
pub mod game_distribution_theme_list_result_type;
pub mod game_distribution_theme_member_table;
pub mod game_distribution_theme_member_type;
pub mod game_distribution_theme_reference_snapshot_type;
pub mod game_distribution_theme_refs_input_type;
pub mod game_distribution_theme_refs_result_type;
pub mod game_distribution_theme_snapshot_type;
pub mod game_distribution_theme_table;
pub mod game_distribution_theme_type;
pub mod game_distribution_uncollect_game_input_type;
@@ -528,6 +536,7 @@ pub mod get_game_distribution_fork_source_and_return_procedure;
pub mod get_game_distribution_game_and_return_procedure;
pub mod get_game_distribution_lineage_and_return_procedure;
pub mod get_game_distribution_my_review_and_return_procedure;
pub mod get_game_distribution_theme_detail_and_return_procedure;
pub mod get_game_distribution_version_and_return_procedure;
pub mod get_llm_router_account_and_return_procedure;
pub mod get_owner_game_distribution_version_and_return_procedure;
@@ -568,6 +577,8 @@ pub mod list_game_distribution_derived_games_and_return_procedure;
pub mod list_game_distribution_games_and_return_procedure;
pub mod list_game_distribution_review_games_and_return_procedure;
pub mod list_game_distribution_reviews_and_return_procedure;
pub mod list_game_distribution_theme_refs_for_root_and_return_procedure;
pub mod list_game_distribution_themes_and_return_procedure;
pub mod list_game_distribution_user_reviews_and_return_procedure;
pub mod list_owner_game_distribution_games_and_return_procedure;
pub mod list_payment_api_keys_and_return_procedure;
@@ -1401,8 +1412,16 @@ pub use game_distribution_review_type::GameDistributionReview;
pub use game_distribution_set_fork_authorization_input_type::GameDistributionSetForkAuthorizationInput;
pub use game_distribution_submit_review_input_type::GameDistributionSubmitReviewInput;
pub use game_distribution_suspend_input_type::GameDistributionSuspendInput;
pub use game_distribution_theme_detail_input_type::GameDistributionThemeDetailInput;
pub use game_distribution_theme_detail_result_type::GameDistributionThemeDetailResult;
pub use game_distribution_theme_list_input_type::GameDistributionThemeListInput;
pub use game_distribution_theme_list_result_type::GameDistributionThemeListResult;
pub use game_distribution_theme_member_table::*;
pub use game_distribution_theme_member_type::GameDistributionThemeMember;
pub use game_distribution_theme_reference_snapshot_type::GameDistributionThemeReferenceSnapshot;
pub use game_distribution_theme_refs_input_type::GameDistributionThemeRefsInput;
pub use game_distribution_theme_refs_result_type::GameDistributionThemeRefsResult;
pub use game_distribution_theme_snapshot_type::GameDistributionThemeSnapshot;
pub use game_distribution_theme_table::*;
pub use game_distribution_theme_type::GameDistributionTheme;
pub use game_distribution_uncollect_game_input_type::GameDistributionUncollectGameInput;
@@ -1442,6 +1461,7 @@ pub use get_game_distribution_fork_source_and_return_procedure::get_game_distrib
pub use get_game_distribution_game_and_return_procedure::get_game_distribution_game_and_return;
pub use get_game_distribution_lineage_and_return_procedure::get_game_distribution_lineage_and_return;
pub use get_game_distribution_my_review_and_return_procedure::get_game_distribution_my_review_and_return;
pub use get_game_distribution_theme_detail_and_return_procedure::get_game_distribution_theme_detail_and_return;
pub use get_game_distribution_version_and_return_procedure::get_game_distribution_version_and_return;
pub use get_llm_router_account_and_return_procedure::get_llm_router_account_and_return;
pub use get_owner_game_distribution_version_and_return_procedure::get_owner_game_distribution_version_and_return;
@@ -1482,6 +1502,8 @@ pub use list_game_distribution_derived_games_and_return_procedure::list_game_dis
pub use list_game_distribution_games_and_return_procedure::list_game_distribution_games_and_return;
pub use list_game_distribution_review_games_and_return_procedure::list_game_distribution_review_games_and_return;
pub use list_game_distribution_reviews_and_return_procedure::list_game_distribution_reviews_and_return;
pub use list_game_distribution_theme_refs_for_root_and_return_procedure::list_game_distribution_theme_refs_for_root_and_return;
pub use list_game_distribution_themes_and_return_procedure::list_game_distribution_themes_and_return;
pub use list_game_distribution_user_reviews_and_return_procedure::list_game_distribution_user_reviews_and_return;
pub use list_owner_game_distribution_games_and_return_procedure::list_owner_game_distribution_games_and_return;
pub use list_payment_api_keys_and_return_procedure::list_payment_api_keys_and_return;
@@ -0,0 +1,15 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeDetailInput {
pub theme_id: String,
}
impl __sdk::InModule for GameDistributionThemeDetailInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,24 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_public_game_snapshot_type::GameDistributionPublicGameSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeDetailResult {
pub ok: bool,
pub theme_id: String,
pub name: String,
pub summary: String,
pub badge: String,
pub member_count: u64,
pub roots: Vec<GameDistributionPublicGameSnapshot>,
pub error_message: Option<String>,
}
impl __sdk::InModule for GameDistributionThemeDetailResult {
type Module = super::RemoteModule;
}
@@ -0,0 +1,16 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeListInput {
pub limit: u32,
pub cursor: Option<String>,
}
impl __sdk::InModule for GameDistributionThemeListInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,20 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_theme_snapshot_type::GameDistributionThemeSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeListResult {
pub ok: bool,
pub themes: Vec<GameDistributionThemeSnapshot>,
pub next_cursor: Option<String>,
pub error_message: Option<String>,
}
impl __sdk::InModule for GameDistributionThemeListResult {
type Module = super::RemoteModule;
}
@@ -0,0 +1,17 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeReferenceSnapshot {
pub theme_id: String,
pub name: String,
pub badge: String,
}
impl __sdk::InModule for GameDistributionThemeReferenceSnapshot {
type Module = super::RemoteModule;
}
@@ -0,0 +1,15 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeRefsInput {
pub game_id: String,
}
impl __sdk::InModule for GameDistributionThemeRefsInput {
type Module = super::RemoteModule;
}
@@ -0,0 +1,19 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_theme_reference_snapshot_type::GameDistributionThemeReferenceSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeRefsResult {
pub ok: bool,
pub themes: Vec<GameDistributionThemeReferenceSnapshot>,
pub error_message: Option<String>,
}
impl __sdk::InModule for GameDistributionThemeRefsResult {
type Module = super::RemoteModule;
}
@@ -0,0 +1,19 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct GameDistributionThemeSnapshot {
pub theme_id: String,
pub name: String,
pub summary: String,
pub badge: String,
pub member_count: u64,
}
impl __sdk::InModule for GameDistributionThemeSnapshot {
type Module = super::RemoteModule;
}
@@ -0,0 +1,62 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_theme_detail_input_type::GameDistributionThemeDetailInput;
use super::game_distribution_theme_detail_result_type::GameDistributionThemeDetailResult;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
struct GetGameDistributionThemeDetailAndReturnArgs {
pub input: GameDistributionThemeDetailInput,
}
impl __sdk::InModule for GetGameDistributionThemeDetailAndReturnArgs {
type Module = super::RemoteModule;
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the procedure `get_game_distribution_theme_detail_and_return`.
///
/// Implemented for [`super::RemoteProcedures`].
pub trait get_game_distribution_theme_detail_and_return {
fn get_game_distribution_theme_detail_and_return(
&self,
input: GameDistributionThemeDetailInput,
) {
self.get_game_distribution_theme_detail_and_return_then(input, |_, _| {});
}
fn get_game_distribution_theme_detail_and_return_then(
&self,
input: GameDistributionThemeDetailInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<GameDistributionThemeDetailResult, __sdk::InternalError>,
) + Send
+ 'static,
);
}
impl get_game_distribution_theme_detail_and_return for super::RemoteProcedures {
fn get_game_distribution_theme_detail_and_return_then(
&self,
input: GameDistributionThemeDetailInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<GameDistributionThemeDetailResult, __sdk::InternalError>,
) + Send
+ 'static,
) {
self.imp
.invoke_procedure_with_callback::<_, GameDistributionThemeDetailResult>(
"get_game_distribution_theme_detail_and_return",
GetGameDistributionThemeDetailAndReturnArgs { input },
__callback,
);
}
}
@@ -0,0 +1,62 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_theme_refs_input_type::GameDistributionThemeRefsInput;
use super::game_distribution_theme_refs_result_type::GameDistributionThemeRefsResult;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
struct ListGameDistributionThemeRefsForRootAndReturnArgs {
pub input: GameDistributionThemeRefsInput,
}
impl __sdk::InModule for ListGameDistributionThemeRefsForRootAndReturnArgs {
type Module = super::RemoteModule;
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the procedure `list_game_distribution_theme_refs_for_root_and_return`.
///
/// Implemented for [`super::RemoteProcedures`].
pub trait list_game_distribution_theme_refs_for_root_and_return {
fn list_game_distribution_theme_refs_for_root_and_return(
&self,
input: GameDistributionThemeRefsInput,
) {
self.list_game_distribution_theme_refs_for_root_and_return_then(input, |_, _| {});
}
fn list_game_distribution_theme_refs_for_root_and_return_then(
&self,
input: GameDistributionThemeRefsInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<GameDistributionThemeRefsResult, __sdk::InternalError>,
) + Send
+ 'static,
);
}
impl list_game_distribution_theme_refs_for_root_and_return for super::RemoteProcedures {
fn list_game_distribution_theme_refs_for_root_and_return_then(
&self,
input: GameDistributionThemeRefsInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<GameDistributionThemeRefsResult, __sdk::InternalError>,
) + Send
+ 'static,
) {
self.imp
.invoke_procedure_with_callback::<_, GameDistributionThemeRefsResult>(
"list_game_distribution_theme_refs_for_root_and_return",
ListGameDistributionThemeRefsForRootAndReturnArgs { input },
__callback,
);
}
}
@@ -0,0 +1,59 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::game_distribution_theme_list_input_type::GameDistributionThemeListInput;
use super::game_distribution_theme_list_result_type::GameDistributionThemeListResult;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
struct ListGameDistributionThemesAndReturnArgs {
pub input: GameDistributionThemeListInput,
}
impl __sdk::InModule for ListGameDistributionThemesAndReturnArgs {
type Module = super::RemoteModule;
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the procedure `list_game_distribution_themes_and_return`.
///
/// Implemented for [`super::RemoteProcedures`].
pub trait list_game_distribution_themes_and_return {
fn list_game_distribution_themes_and_return(&self, input: GameDistributionThemeListInput) {
self.list_game_distribution_themes_and_return_then(input, |_, _| {});
}
fn list_game_distribution_themes_and_return_then(
&self,
input: GameDistributionThemeListInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<GameDistributionThemeListResult, __sdk::InternalError>,
) + Send
+ 'static,
);
}
impl list_game_distribution_themes_and_return for super::RemoteProcedures {
fn list_game_distribution_themes_and_return_then(
&self,
input: GameDistributionThemeListInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<GameDistributionThemeListResult, __sdk::InternalError>,
) + Send
+ 'static,
) {
self.imp
.invoke_procedure_with_callback::<_, GameDistributionThemeListResult>(
"list_game_distribution_themes_and_return",
ListGameDistributionThemesAndReturnArgs { input },
__callback,
);
}
}
File diff suppressed because it is too large Load Diff