feat(游戏共创): 共创主题(一)数据模型与领域纯函数
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m30s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m12s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m44s
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m30s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 4m12s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m44s
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
按 `docs/【技术方案】游戏共创与作品Fork-2026-10-03.md §3.10` 与里程碑《共创主题与作品树-2026-10-06》的清单 A/B/F 落地(本块**不含** procedure / 路由)。
- **表**:`game_distribution_theme`(`theme_id` 主键、`name`/`summary`/`badge`/`sort_order`/`status ∈ draft|published|archived`/`created_by_user_id`/`created_at`/`updated_at`)+ `game_distribution_theme_member`(确定性主键 `member_id = "{theme_id}:{root_game_id}"`,`theme_id`、`root_game_id` 各具名 btree 索引,`sort_order`、`created_at`);归档 / 下架只改公开投影,不删成员行。`migration.rs` 白名单登记两张表(随迁移导出/导入)。
- **生成绑定**:4 个 `game_distribution_theme*` 生成文件 + `module_bindings.rs` 入口(纯追加)。生成时**不覆盖工作树**(本仓共享工作树禁止 git 写命令):先 `spacetime generate --lang rust --out-dir <仓外临时目录>`,rustfmt 后只拷回本次相关文件,避免上一轮踩过的「rustfmt 漂移把别人文件一起改」。
- **领域纯函数**(`module-game-distribution/src/theme.rs`,风格照同目录 `collection.rs`):状态合法/公开可见判定、`game_distribution_theme_member_id`、成员可见性(**委托** `collection.rs` 的判定,不复制第二套)、`game_distribution_theme_root_acceptable(has_lineage_row)`、页大小(缺省 20 / 上限 50 / 0 取默认 / 超界截断)、游标编解码(`"{createdAtMicros}:{themeId}"`,Err 文案「主题列表游标格式无效」,已核对不含 404/409 关键词)、`sort_public_themes`(`created_at` 倒序 + `theme_id` 兜底)、`page_public_themes`(排序 → retain 游标之后 → 多取一条判 has_more;**先过滤再切页**的顺序语义写进文档注释)、`sort_theme_members`(`sort_order` 升序 + `member_id` 兜底)与 `page_theme_members`。
- **契约**:`shared-contracts` 新增 `GameDistributionThemeStatus` / `GameDistributionThemeReference` / `GameDistributionThemeSummary` / `GameDistributionThemeListResponse` / `GameDistributionThemeDetail` / `GameDistributionCreateThemeRequest` / `GameDistributionUpdateThemeRequest` / `GameDistributionUpsertThemeMemberRequest`,`GameDistributionGameSummary` 追加可选 `themes`(按 `collected` 先例只在详情路径下发);TS 镜像同步;parity 登记 **58 组**(响应构建器待路由落地后再登记,parity 要求函数真实存在)。
- **数据契约表目录**:补两张表小节,94 → **96**。
- **测试**:`theme.rs` 16 个单测(成员 id 确定性、状态三态与公开可见、成员可见性逐格与收藏判定等价、根判定、页大小边界、游标往返与非法输入、排序稳定性与同 `sort_order` 兜底、分页不重不漏)。
- **门禁**:wasm build 0;`cargo check --all-targets` 0;`cargo test -p module-game-distribution` **97 passed**;`cargo test -p spacetime-module` 274 passed / 1 ignored;DTO parity **58 组**;`check:spacetime-schema` 0(**96** tables);`check:server-rs-ddd` 0;`check:encoding` 0(5388 files);`cargo fmt --all -- --check` 0;`git diff --check` 0(8 个改动文件 0 删除行)。
This commit is contained in:
@@ -9,6 +9,7 @@ mod package;
|
||||
mod project_bundle;
|
||||
mod release;
|
||||
mod reviews;
|
||||
mod theme;
|
||||
|
||||
pub use reviews::{
|
||||
ReviewModerationValidationError, UserReviewValidationError, normalize_review_comment,
|
||||
@@ -57,3 +58,14 @@ pub use release::{
|
||||
MAX_RELEASE_ASSET_BYTES, ReleaseAssetError, extract_release_asset,
|
||||
normalize_release_asset_path, release_asset_content_type,
|
||||
};
|
||||
pub use theme::{
|
||||
GAME_DISTRIBUTION_THEME_PAGE_LIMIT_DEFAULT, GAME_DISTRIBUTION_THEME_PAGE_LIMIT_MAX,
|
||||
GAME_DISTRIBUTION_THEME_STATUS_ARCHIVED, GAME_DISTRIBUTION_THEME_STATUS_DRAFT,
|
||||
GAME_DISTRIBUTION_THEME_STATUS_PUBLISHED, GAME_DISTRIBUTION_THEME_STATUSES,
|
||||
GameDistributionThemeMemberPageItem, GameDistributionThemePageItem,
|
||||
encode_game_distribution_theme_cursor, game_distribution_theme_member_id,
|
||||
game_distribution_theme_member_visible, game_distribution_theme_page_limit,
|
||||
game_distribution_theme_public_visible, game_distribution_theme_root_acceptable,
|
||||
game_distribution_theme_status_valid, page_public_themes, page_theme_members,
|
||||
parse_game_distribution_theme_cursor, sort_public_themes, sort_theme_members,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -223,6 +223,13 @@ pub struct GameDistributionGameSummary {
|
||||
/// 的真实投影,不是客户端本地状态。
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub collected: Option<bool>,
|
||||
/// 该作品所属的**公开**共创主题:先取作品的根、再按根反查成员行(跨主题多归属,因此是数组)。
|
||||
///
|
||||
/// **只有公开详情下发**(匿名与登录都发;没有所属主题时发空数组,展示层不渲染空容器);
|
||||
/// 公开列表与作者侧不发该键。第 N 代作品同样能看到主题——反查用的是**根**,不是作品自身。
|
||||
/// 排序与公开主题列表共用同一份比较器(创建时间倒序 + `theme_id` 升序兜底)。
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub themes: Option<Vec<GameDistributionThemeReference>>,
|
||||
}
|
||||
|
||||
/// 作品级共创(Fork)授权档位:只允许单向提升开放度。
|
||||
@@ -393,6 +400,121 @@ pub struct GameDistributionMyCollectionsResponse {
|
||||
pub next_cursor: Option<String>,
|
||||
}
|
||||
|
||||
/// 共创主题的三态处置:`draft`(未发布)/ `published`(公开可见)/ `archived`(归档下架)。
|
||||
///
|
||||
/// 后台写接口的入参用这个枚举而不是裸字符串:非法取值在反序列化阶段即被拒绝(api-server 映射
|
||||
/// 400),不会带着一个「未定义状态」进入事务。模块侧的数据列仍是字符串,配套白名单是
|
||||
/// `module_game_distribution::GAME_DISTRIBUTION_THEME_STATUSES`。
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum GameDistributionThemeStatus {
|
||||
/// 已创建但未对外发布:公开侧任何投影都看不到。
|
||||
#[default]
|
||||
Draft,
|
||||
/// 已发布:公开列表、公开详情与作品详情的 `themes` 都会出现。
|
||||
Published,
|
||||
/// 已归档下架:不再公开,但主题行与成员行都保留。
|
||||
Archived,
|
||||
}
|
||||
|
||||
/// 作品详情「所属主题」增量的单个条目:只够渲染一个跳转入口。
|
||||
///
|
||||
/// 不含简介与成员数——详情页只需要「这条作品属于哪些主题」和一个能点进去的名字与角标,
|
||||
/// 完整信息在主题页(`GameDistributionThemeDetail`)取。
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionThemeReference {
|
||||
pub theme_id: String,
|
||||
pub name: String,
|
||||
pub badge: String,
|
||||
}
|
||||
|
||||
/// 公开主题列表的单条:主题名、简介、角标与**当前公开可见成员数**。
|
||||
///
|
||||
/// `member_count` 与详情响应的 `roots` 长度是同一个数(同一份成员可见性判定):若回报「全部成员
|
||||
/// 行数」,运营就能通过计数变化探测存在草稿 / 被下架成员,且它会与 `roots` 长度对不上。
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionThemeSummary {
|
||||
pub theme_id: String,
|
||||
pub name: String,
|
||||
pub summary: String,
|
||||
pub badge: String,
|
||||
pub member_count: u64,
|
||||
}
|
||||
|
||||
/// 公开主题列表接口(`GET /api/game-distribution/themes`)的响应体。
|
||||
///
|
||||
/// 只含 `status == published` 的主题。分页沿用既有游标惯例:默认 20 条、上限 50 条、超界截断;
|
||||
/// `next_cursor` 是真实游标(`"{created_at_micros}:{theme_id}"`),最后一页为 `null`;游标格式
|
||||
/// 非法时服务端返回 400。排序为创建时间倒序 + `theme_id` 升序兜底(全序,翻页不重不漏)。
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionThemeListResponse {
|
||||
pub themes: Vec<GameDistributionThemeSummary>,
|
||||
#[serde(default)]
|
||||
pub next_cursor: Option<String>,
|
||||
}
|
||||
|
||||
/// 公开主题详情接口(`GET /api/game-distribution/themes/{theme_id}`)的响应体。
|
||||
///
|
||||
/// 顶层扁平形状与 `GET /games/{gameId}` 同形,不引入第二套包装。`roots` 逐条是**公开目录同一份**
|
||||
/// 作品投影(`GameDistributionGameSummary`),排序为 `sort_order` 升序 + `member_id` 升序兜底。
|
||||
/// 主题不存在或未发布时接口返回 404(不返回空壳);已发布但可见成员为空时返回 200 + 空 `roots`。
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionThemeDetail {
|
||||
pub theme_id: String,
|
||||
pub name: String,
|
||||
pub summary: String,
|
||||
pub badge: String,
|
||||
pub member_count: u64,
|
||||
pub roots: Vec<GameDistributionGameSummary>,
|
||||
}
|
||||
|
||||
/// 后台创建主题(`POST /admin/api/game-distribution/themes`)的请求体。
|
||||
///
|
||||
/// `name` 必填且非空(空名由 api-server 映射 400);其余字段省略时按「空文本 / 排序 0 /
|
||||
/// `draft`」落库——与表列默认一致,因此「省略」与「显式传默认」是同一个请求,幂等摘要也相同。
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionCreateThemeRequest {
|
||||
pub name: String,
|
||||
#[serde(default)]
|
||||
pub summary: String,
|
||||
#[serde(default)]
|
||||
pub badge: String,
|
||||
#[serde(default)]
|
||||
pub sort_order: i64,
|
||||
#[serde(default)]
|
||||
pub status: GameDistributionThemeStatus,
|
||||
}
|
||||
|
||||
/// 后台更新主题(`PUT /admin/api/game-distribution/themes/{theme_id}`)的请求体。
|
||||
///
|
||||
/// **整体覆盖**这几个字段(不是部分更新):字段都必填,避免「省略 = 保留旧值」与「省略 = 清空」
|
||||
/// 两种解释在客户端之间漂移。`updated_at` 每次生效即刷新。
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionUpdateThemeRequest {
|
||||
pub name: String,
|
||||
pub summary: String,
|
||||
pub badge: String,
|
||||
pub sort_order: i64,
|
||||
pub status: GameDistributionThemeStatus,
|
||||
}
|
||||
|
||||
/// 后台增 / 改成员(`PUT /admin/api/game-distribution/themes/{theme_id}/members/{root_game_id}`)的请求体。
|
||||
///
|
||||
/// 成员身份完全由路径给出(`theme_id` + `root_game_id`),body 只承载运营权重;重复调用由确定性
|
||||
/// 主键保证幂等(同主题同根只有一行,`created_at` 首次写入后不再变)。
|
||||
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionUpsertThemeMemberRequest {
|
||||
#[serde(default)]
|
||||
pub sort_order: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GameDistributionCreateGameRequest {
|
||||
|
||||
@@ -487,6 +487,10 @@ 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_member_table;
|
||||
pub mod game_distribution_theme_member_type;
|
||||
pub mod game_distribution_theme_table;
|
||||
pub mod game_distribution_theme_type;
|
||||
pub mod game_distribution_uncollect_game_input_type;
|
||||
pub mod game_distribution_unpublish_input_type;
|
||||
pub mod game_distribution_update_metadata_input_type;
|
||||
@@ -1397,6 +1401,10 @@ 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_member_table::*;
|
||||
pub use game_distribution_theme_member_type::GameDistributionThemeMember;
|
||||
pub use game_distribution_theme_table::*;
|
||||
pub use game_distribution_theme_type::GameDistributionTheme;
|
||||
pub use game_distribution_uncollect_game_input_type::GameDistributionUncollectGameInput;
|
||||
pub use game_distribution_unpublish_input_type::GameDistributionUnpublishInput;
|
||||
pub use game_distribution_update_metadata_input_type::GameDistributionUpdateMetadataInput;
|
||||
@@ -1985,6 +1993,8 @@ pub struct DbUpdate {
|
||||
game_distribution_review: __sdk::TableUpdate<GameDistributionReview>,
|
||||
game_distribution_review_moderation_log:
|
||||
__sdk::TableUpdate<GameDistributionReviewModerationLog>,
|
||||
game_distribution_theme: __sdk::TableUpdate<GameDistributionTheme>,
|
||||
game_distribution_theme_member: __sdk::TableUpdate<GameDistributionThemeMember>,
|
||||
game_distribution_version: __sdk::TableUpdate<GameDistributionVersion>,
|
||||
llm_router_account: __sdk::TableUpdate<LlmRouterAccount>,
|
||||
llm_router_billing_checkpoint: __sdk::TableUpdate<LlmRouterBillingCheckpoint>,
|
||||
@@ -2221,6 +2231,14 @@ impl TryFrom<__ws::v2::TransactionUpdate> for DbUpdate {
|
||||
)?,
|
||||
)
|
||||
}
|
||||
"game_distribution_theme" => db_update.game_distribution_theme.append(
|
||||
game_distribution_theme_table::parse_table_update(table_update)?,
|
||||
),
|
||||
"game_distribution_theme_member" => {
|
||||
db_update.game_distribution_theme_member.append(
|
||||
game_distribution_theme_member_table::parse_table_update(table_update)?,
|
||||
)
|
||||
}
|
||||
"game_distribution_version" => db_update.game_distribution_version.append(
|
||||
game_distribution_version_table::parse_table_update(table_update)?,
|
||||
),
|
||||
@@ -2653,6 +2671,18 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
&self.game_distribution_review_moderation_log,
|
||||
)
|
||||
.with_updates_by_pk(|row| &row.operation_id);
|
||||
diff.game_distribution_theme = cache
|
||||
.apply_diff_to_table::<GameDistributionTheme>(
|
||||
"game_distribution_theme",
|
||||
&self.game_distribution_theme,
|
||||
)
|
||||
.with_updates_by_pk(|row| &row.theme_id);
|
||||
diff.game_distribution_theme_member = cache
|
||||
.apply_diff_to_table::<GameDistributionThemeMember>(
|
||||
"game_distribution_theme_member",
|
||||
&self.game_distribution_theme_member,
|
||||
)
|
||||
.with_updates_by_pk(|row| &row.member_id);
|
||||
diff.game_distribution_version = cache
|
||||
.apply_diff_to_table::<GameDistributionVersion>(
|
||||
"game_distribution_version",
|
||||
@@ -3044,6 +3074,12 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
"game_distribution_review_moderation_log" => db_update
|
||||
.game_distribution_review_moderation_log
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"game_distribution_theme" => db_update
|
||||
.game_distribution_theme
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"game_distribution_theme_member" => db_update
|
||||
.game_distribution_theme_member
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
"game_distribution_version" => db_update
|
||||
.game_distribution_version
|
||||
.append(__sdk::parse_row_list_as_inserts(table_rows.rows)?),
|
||||
@@ -3339,6 +3375,12 @@ impl __sdk::DbUpdate for DbUpdate {
|
||||
"game_distribution_review_moderation_log" => db_update
|
||||
.game_distribution_review_moderation_log
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"game_distribution_theme" => db_update
|
||||
.game_distribution_theme
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"game_distribution_theme_member" => db_update
|
||||
.game_distribution_theme_member
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
"game_distribution_version" => db_update
|
||||
.game_distribution_version
|
||||
.append(__sdk::parse_row_list_as_deletes(table_rows.rows)?),
|
||||
@@ -3542,6 +3584,8 @@ pub struct AppliedDiff<'r> {
|
||||
game_distribution_review: __sdk::TableAppliedDiff<'r, GameDistributionReview>,
|
||||
game_distribution_review_moderation_log:
|
||||
__sdk::TableAppliedDiff<'r, GameDistributionReviewModerationLog>,
|
||||
game_distribution_theme: __sdk::TableAppliedDiff<'r, GameDistributionTheme>,
|
||||
game_distribution_theme_member: __sdk::TableAppliedDiff<'r, GameDistributionThemeMember>,
|
||||
game_distribution_version: __sdk::TableAppliedDiff<'r, GameDistributionVersion>,
|
||||
llm_router_account: __sdk::TableAppliedDiff<'r, LlmRouterAccount>,
|
||||
llm_router_billing_checkpoint: __sdk::TableAppliedDiff<'r, LlmRouterBillingCheckpoint>,
|
||||
@@ -3842,6 +3886,16 @@ impl<'r> __sdk::AppliedDiff<'r> for AppliedDiff<'r> {
|
||||
&self.game_distribution_review_moderation_log,
|
||||
event,
|
||||
);
|
||||
callbacks.invoke_table_row_callbacks::<GameDistributionTheme>(
|
||||
"game_distribution_theme",
|
||||
&self.game_distribution_theme,
|
||||
event,
|
||||
);
|
||||
callbacks.invoke_table_row_callbacks::<GameDistributionThemeMember>(
|
||||
"game_distribution_theme_member",
|
||||
&self.game_distribution_theme_member,
|
||||
event,
|
||||
);
|
||||
callbacks.invoke_table_row_callbacks::<GameDistributionVersion>(
|
||||
"game_distribution_version",
|
||||
&self.game_distribution_version,
|
||||
@@ -4768,6 +4822,8 @@ impl __sdk::SpacetimeModule for RemoteModule {
|
||||
game_distribution_lineage_table::register_table(client_cache);
|
||||
game_distribution_review_table::register_table(client_cache);
|
||||
game_distribution_review_moderation_log_table::register_table(client_cache);
|
||||
game_distribution_theme_table::register_table(client_cache);
|
||||
game_distribution_theme_member_table::register_table(client_cache);
|
||||
game_distribution_version_table::register_table(client_cache);
|
||||
llm_router_account_table::register_table(client_cache);
|
||||
llm_router_billing_checkpoint_table::register_table(client_cache);
|
||||
@@ -4864,6 +4920,8 @@ impl __sdk::SpacetimeModule for RemoteModule {
|
||||
"game_distribution_lineage",
|
||||
"game_distribution_review",
|
||||
"game_distribution_review_moderation_log",
|
||||
"game_distribution_theme",
|
||||
"game_distribution_theme_member",
|
||||
"game_distribution_version",
|
||||
"llm_router_account",
|
||||
"llm_router_billing_checkpoint",
|
||||
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
// 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 super::game_distribution_theme_member_type::GameDistributionThemeMember;
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
/// Table handle for the table `game_distribution_theme_member`.
|
||||
///
|
||||
/// Obtain a handle from the [`GameDistributionThemeMemberTableAccess::game_distribution_theme_member`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.game_distribution_theme_member()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.game_distribution_theme_member().on_insert(...)`.
|
||||
pub struct GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<GameDistributionThemeMember>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
/// Lifetime-aware accessor marker for the table `game_distribution_theme_member`.
|
||||
pub struct GameDistributionThemeMemberTableAccessor;
|
||||
|
||||
impl __sdk::TableAccessor<super::RemoteTables> for GameDistributionThemeMemberTableAccessor {
|
||||
type Row = GameDistributionThemeMember;
|
||||
type Handle<'db> = GameDistributionThemeMemberTableHandle<'db>;
|
||||
|
||||
fn get<'db>(db: &'db super::RemoteTables) -> Self::Handle<'db> {
|
||||
db.game_distribution_theme_member()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `game_distribution_theme_member`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait GameDistributionThemeMemberTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`GameDistributionThemeMemberTableHandle`], which mediates access to the table `game_distribution_theme_member`.
|
||||
fn game_distribution_theme_member(&self) -> GameDistributionThemeMemberTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl GameDistributionThemeMemberTableAccess for super::RemoteTables {
|
||||
fn game_distribution_theme_member(&self) -> GameDistributionThemeMemberTableHandle<'_> {
|
||||
GameDistributionThemeMemberTableHandle {
|
||||
imp: self
|
||||
.imp
|
||||
.get_table::<GameDistributionThemeMember>("game_distribution_theme_member"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GameDistributionThemeMemberInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct GameDistributionThemeMemberDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableLike for GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
type Row = GameDistributionThemeMember;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = GameDistributionThemeMember> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::Table for GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
type Row = GameDistributionThemeMember;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = GameDistributionThemeMember> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
|
||||
type InsertCallbackId = GameDistributionThemeMemberInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeMemberInsertCallbackId {
|
||||
GameDistributionThemeMemberInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: GameDistributionThemeMemberInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = GameDistributionThemeMemberDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeMemberDeleteCallbackId {
|
||||
GameDistributionThemeMemberDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: GameDistributionThemeMemberDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::WithInsert for GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
type InsertCallbackId = GameDistributionThemeMemberInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeMemberInsertCallbackId {
|
||||
GameDistributionThemeMemberInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: GameDistributionThemeMemberInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::WithDelete for GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
type DeleteCallbackId = GameDistributionThemeMemberDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeMemberDeleteCallbackId {
|
||||
GameDistributionThemeMemberDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: GameDistributionThemeMemberDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GameDistributionThemeMemberUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
type UpdateCallbackId = GameDistributionThemeMemberUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeMemberUpdateCallbackId {
|
||||
GameDistributionThemeMemberUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: GameDistributionThemeMemberUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::WithUpdate for GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
type UpdateCallbackId = GameDistributionThemeMemberUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeMemberUpdateCallbackId {
|
||||
GameDistributionThemeMemberUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: GameDistributionThemeMemberUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `member_id` unique index on the table `game_distribution_theme_member`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`GameDistributionThemeMemberMemberIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.game_distribution_theme_member().member_id().find(...)`.
|
||||
pub struct GameDistributionThemeMemberMemberIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<GameDistributionThemeMember, String>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> GameDistributionThemeMemberTableHandle<'ctx> {
|
||||
/// Get a handle on the `member_id` unique index on the table `game_distribution_theme_member`.
|
||||
pub fn member_id(&self) -> GameDistributionThemeMemberMemberIdUnique<'ctx> {
|
||||
GameDistributionThemeMemberMemberIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<String>("member_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> GameDistributionThemeMemberMemberIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `member_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &String) -> Option<GameDistributionThemeMember> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table = client_cache
|
||||
.get_or_make_table::<GameDistributionThemeMember>("game_distribution_theme_member");
|
||||
_table.add_unique_constraint::<String>("member_id", |row| &row.member_id);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<GameDistributionThemeMember>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse(
|
||||
"TableUpdate<GameDistributionThemeMember>",
|
||||
"TableUpdate",
|
||||
)
|
||||
.with_cause(e)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `GameDistributionThemeMember`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait game_distribution_theme_memberQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `GameDistributionThemeMember`.
|
||||
fn game_distribution_theme_member(
|
||||
&self,
|
||||
) -> __sdk::__query_builder::Table<GameDistributionThemeMember>;
|
||||
}
|
||||
|
||||
impl game_distribution_theme_memberQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn game_distribution_theme_member(
|
||||
&self,
|
||||
) -> __sdk::__query_builder::Table<GameDistributionThemeMember> {
|
||||
__sdk::__query_builder::Table::new("game_distribution_theme_member")
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// 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 GameDistributionThemeMember {
|
||||
pub member_id: String,
|
||||
pub theme_id: String,
|
||||
pub root_game_id: String,
|
||||
pub sort_order: i64,
|
||||
pub created_at: __sdk::Timestamp,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for GameDistributionThemeMember {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
/// Column accessor struct for the table `GameDistributionThemeMember`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct GameDistributionThemeMemberCols {
|
||||
pub member_id: __sdk::__query_builder::Col<GameDistributionThemeMember, String>,
|
||||
pub theme_id: __sdk::__query_builder::Col<GameDistributionThemeMember, String>,
|
||||
pub root_game_id: __sdk::__query_builder::Col<GameDistributionThemeMember, String>,
|
||||
pub sort_order: __sdk::__query_builder::Col<GameDistributionThemeMember, i64>,
|
||||
pub created_at: __sdk::__query_builder::Col<GameDistributionThemeMember, __sdk::Timestamp>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for GameDistributionThemeMember {
|
||||
type Cols = GameDistributionThemeMemberCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
GameDistributionThemeMemberCols {
|
||||
member_id: __sdk::__query_builder::Col::new(table_name, "member_id"),
|
||||
theme_id: __sdk::__query_builder::Col::new(table_name, "theme_id"),
|
||||
root_game_id: __sdk::__query_builder::Col::new(table_name, "root_game_id"),
|
||||
sort_order: __sdk::__query_builder::Col::new(table_name, "sort_order"),
|
||||
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexed column accessor struct for the table `GameDistributionThemeMember`.
|
||||
///
|
||||
/// Provides typed access to indexed columns for query building.
|
||||
pub struct GameDistributionThemeMemberIxCols {
|
||||
pub member_id: __sdk::__query_builder::IxCol<GameDistributionThemeMember, String>,
|
||||
pub root_game_id: __sdk::__query_builder::IxCol<GameDistributionThemeMember, String>,
|
||||
pub theme_id: __sdk::__query_builder::IxCol<GameDistributionThemeMember, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasIxCols for GameDistributionThemeMember {
|
||||
type IxCols = GameDistributionThemeMemberIxCols;
|
||||
fn ix_cols(table_name: &'static str) -> Self::IxCols {
|
||||
GameDistributionThemeMemberIxCols {
|
||||
member_id: __sdk::__query_builder::IxCol::new(table_name, "member_id"),
|
||||
root_game_id: __sdk::__query_builder::IxCol::new(table_name, "root_game_id"),
|
||||
theme_id: __sdk::__query_builder::IxCol::new(table_name, "theme_id"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::CanBeLookupTable for GameDistributionThemeMember {}
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
// 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 super::game_distribution_theme_type::GameDistributionTheme;
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
/// Table handle for the table `game_distribution_theme`.
|
||||
///
|
||||
/// Obtain a handle from the [`GameDistributionThemeTableAccess::game_distribution_theme`] method on [`super::RemoteTables`],
|
||||
/// like `ctx.db.game_distribution_theme()`.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.game_distribution_theme().on_insert(...)`.
|
||||
pub struct GameDistributionThemeTableHandle<'ctx> {
|
||||
imp: __sdk::TableHandle<GameDistributionTheme>,
|
||||
ctx: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
/// Lifetime-aware accessor marker for the table `game_distribution_theme`.
|
||||
pub struct GameDistributionThemeTableAccessor;
|
||||
|
||||
impl __sdk::TableAccessor<super::RemoteTables> for GameDistributionThemeTableAccessor {
|
||||
type Row = GameDistributionTheme;
|
||||
type Handle<'db> = GameDistributionThemeTableHandle<'db>;
|
||||
|
||||
fn get<'db>(db: &'db super::RemoteTables) -> Self::Handle<'db> {
|
||||
db.game_distribution_theme()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the table `game_distribution_theme`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteTables`].
|
||||
pub trait GameDistributionThemeTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Obtain a [`GameDistributionThemeTableHandle`], which mediates access to the table `game_distribution_theme`.
|
||||
fn game_distribution_theme(&self) -> GameDistributionThemeTableHandle<'_>;
|
||||
}
|
||||
|
||||
impl GameDistributionThemeTableAccess for super::RemoteTables {
|
||||
fn game_distribution_theme(&self) -> GameDistributionThemeTableHandle<'_> {
|
||||
GameDistributionThemeTableHandle {
|
||||
imp: self
|
||||
.imp
|
||||
.get_table::<GameDistributionTheme>("game_distribution_theme"),
|
||||
ctx: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GameDistributionThemeInsertCallbackId(__sdk::CallbackId);
|
||||
pub struct GameDistributionThemeDeleteCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableLike for GameDistributionThemeTableHandle<'ctx> {
|
||||
type Row = GameDistributionTheme;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = GameDistributionTheme> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::Table for GameDistributionThemeTableHandle<'ctx> {
|
||||
type Row = GameDistributionTheme;
|
||||
type EventContext = super::EventContext;
|
||||
|
||||
fn count(&self) -> u64 {
|
||||
self.imp.count()
|
||||
}
|
||||
fn iter(&self) -> impl Iterator<Item = GameDistributionTheme> + '_ {
|
||||
self.imp.iter()
|
||||
}
|
||||
|
||||
type InsertCallbackId = GameDistributionThemeInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeInsertCallbackId {
|
||||
GameDistributionThemeInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: GameDistributionThemeInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
|
||||
type DeleteCallbackId = GameDistributionThemeDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeDeleteCallbackId {
|
||||
GameDistributionThemeDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: GameDistributionThemeDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::WithInsert for GameDistributionThemeTableHandle<'ctx> {
|
||||
type InsertCallbackId = GameDistributionThemeInsertCallbackId;
|
||||
|
||||
fn on_insert(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeInsertCallbackId {
|
||||
GameDistributionThemeInsertCallbackId(self.imp.on_insert(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_insert(&self, callback: GameDistributionThemeInsertCallbackId) {
|
||||
self.imp.remove_on_insert(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::WithDelete for GameDistributionThemeTableHandle<'ctx> {
|
||||
type DeleteCallbackId = GameDistributionThemeDeleteCallbackId;
|
||||
|
||||
fn on_delete(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeDeleteCallbackId {
|
||||
GameDistributionThemeDeleteCallbackId(self.imp.on_delete(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_delete(&self, callback: GameDistributionThemeDeleteCallbackId) {
|
||||
self.imp.remove_on_delete(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GameDistributionThemeUpdateCallbackId(__sdk::CallbackId);
|
||||
|
||||
impl<'ctx> __sdk::TableWithPrimaryKey for GameDistributionThemeTableHandle<'ctx> {
|
||||
type UpdateCallbackId = GameDistributionThemeUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeUpdateCallbackId {
|
||||
GameDistributionThemeUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: GameDistributionThemeUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> __sdk::WithUpdate for GameDistributionThemeTableHandle<'ctx> {
|
||||
type UpdateCallbackId = GameDistributionThemeUpdateCallbackId;
|
||||
|
||||
fn on_update(
|
||||
&self,
|
||||
callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static,
|
||||
) -> GameDistributionThemeUpdateCallbackId {
|
||||
GameDistributionThemeUpdateCallbackId(self.imp.on_update(Box::new(callback)))
|
||||
}
|
||||
|
||||
fn remove_on_update(&self, callback: GameDistributionThemeUpdateCallbackId) {
|
||||
self.imp.remove_on_update(callback.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access to the `theme_id` unique index on the table `game_distribution_theme`,
|
||||
/// which allows point queries on the field of the same name
|
||||
/// via the [`GameDistributionThemeThemeIdUnique::find`] method.
|
||||
///
|
||||
/// Users are encouraged not to explicitly reference this type,
|
||||
/// but to directly chain method calls,
|
||||
/// like `ctx.db.game_distribution_theme().theme_id().find(...)`.
|
||||
pub struct GameDistributionThemeThemeIdUnique<'ctx> {
|
||||
imp: __sdk::UniqueConstraintHandle<GameDistributionTheme, String>,
|
||||
phantom: std::marker::PhantomData<&'ctx super::RemoteTables>,
|
||||
}
|
||||
|
||||
impl<'ctx> GameDistributionThemeTableHandle<'ctx> {
|
||||
/// Get a handle on the `theme_id` unique index on the table `game_distribution_theme`.
|
||||
pub fn theme_id(&self) -> GameDistributionThemeThemeIdUnique<'ctx> {
|
||||
GameDistributionThemeThemeIdUnique {
|
||||
imp: self.imp.get_unique_constraint::<String>("theme_id"),
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> GameDistributionThemeThemeIdUnique<'ctx> {
|
||||
/// Find the subscribed row whose `theme_id` column value is equal to `col_val`,
|
||||
/// if such a row is present in the client cache.
|
||||
pub fn find(&self, col_val: &String) -> Option<GameDistributionTheme> {
|
||||
self.imp.find(col_val)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn register_table(client_cache: &mut __sdk::ClientCache<super::RemoteModule>) {
|
||||
let _table = client_cache.get_or_make_table::<GameDistributionTheme>("game_distribution_theme");
|
||||
_table.add_unique_constraint::<String>("theme_id", |row| &row.theme_id);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(super) fn parse_table_update(
|
||||
raw_updates: __ws::v2::TableUpdate,
|
||||
) -> __sdk::Result<__sdk::TableUpdate<GameDistributionTheme>> {
|
||||
__sdk::TableUpdate::parse_table_update(raw_updates).map_err(|e| {
|
||||
__sdk::InternalError::failed_parse("TableUpdate<GameDistributionTheme>", "TableUpdate")
|
||||
.with_cause(e)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for query builder access to the table `GameDistributionTheme`.
|
||||
///
|
||||
/// Implemented for [`__sdk::QueryTableAccessor`].
|
||||
pub trait game_distribution_themeQueryTableAccess {
|
||||
#[allow(non_snake_case)]
|
||||
/// Get a query builder for the table `GameDistributionTheme`.
|
||||
fn game_distribution_theme(&self) -> __sdk::__query_builder::Table<GameDistributionTheme>;
|
||||
}
|
||||
|
||||
impl game_distribution_themeQueryTableAccess for __sdk::QueryTableAccessor {
|
||||
fn game_distribution_theme(&self) -> __sdk::__query_builder::Table<GameDistributionTheme> {
|
||||
__sdk::__query_builder::Table::new("game_distribution_theme")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// 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 GameDistributionTheme {
|
||||
pub theme_id: String,
|
||||
pub name: String,
|
||||
pub summary: String,
|
||||
pub badge: String,
|
||||
pub sort_order: i64,
|
||||
pub status: String,
|
||||
pub created_by_user_id: String,
|
||||
pub created_at: __sdk::Timestamp,
|
||||
pub updated_at: __sdk::Timestamp,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for GameDistributionTheme {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
/// Column accessor struct for the table `GameDistributionTheme`.
|
||||
///
|
||||
/// Provides typed access to columns for query building.
|
||||
pub struct GameDistributionThemeCols {
|
||||
pub theme_id: __sdk::__query_builder::Col<GameDistributionTheme, String>,
|
||||
pub name: __sdk::__query_builder::Col<GameDistributionTheme, String>,
|
||||
pub summary: __sdk::__query_builder::Col<GameDistributionTheme, String>,
|
||||
pub badge: __sdk::__query_builder::Col<GameDistributionTheme, String>,
|
||||
pub sort_order: __sdk::__query_builder::Col<GameDistributionTheme, i64>,
|
||||
pub status: __sdk::__query_builder::Col<GameDistributionTheme, String>,
|
||||
pub created_by_user_id: __sdk::__query_builder::Col<GameDistributionTheme, String>,
|
||||
pub created_at: __sdk::__query_builder::Col<GameDistributionTheme, __sdk::Timestamp>,
|
||||
pub updated_at: __sdk::__query_builder::Col<GameDistributionTheme, __sdk::Timestamp>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasCols for GameDistributionTheme {
|
||||
type Cols = GameDistributionThemeCols;
|
||||
fn cols(table_name: &'static str) -> Self::Cols {
|
||||
GameDistributionThemeCols {
|
||||
theme_id: __sdk::__query_builder::Col::new(table_name, "theme_id"),
|
||||
name: __sdk::__query_builder::Col::new(table_name, "name"),
|
||||
summary: __sdk::__query_builder::Col::new(table_name, "summary"),
|
||||
badge: __sdk::__query_builder::Col::new(table_name, "badge"),
|
||||
sort_order: __sdk::__query_builder::Col::new(table_name, "sort_order"),
|
||||
status: __sdk::__query_builder::Col::new(table_name, "status"),
|
||||
created_by_user_id: __sdk::__query_builder::Col::new(table_name, "created_by_user_id"),
|
||||
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
|
||||
updated_at: __sdk::__query_builder::Col::new(table_name, "updated_at"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indexed column accessor struct for the table `GameDistributionTheme`.
|
||||
///
|
||||
/// Provides typed access to indexed columns for query building.
|
||||
pub struct GameDistributionThemeIxCols {
|
||||
pub created_at: __sdk::__query_builder::IxCol<GameDistributionTheme, __sdk::Timestamp>,
|
||||
pub theme_id: __sdk::__query_builder::IxCol<GameDistributionTheme, String>,
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::HasIxCols for GameDistributionTheme {
|
||||
type IxCols = GameDistributionThemeIxCols;
|
||||
fn ix_cols(table_name: &'static str) -> Self::IxCols {
|
||||
GameDistributionThemeIxCols {
|
||||
created_at: __sdk::__query_builder::IxCol::new(table_name, "created_at"),
|
||||
theme_id: __sdk::__query_builder::IxCol::new(table_name, "theme_id"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl __sdk::__query_builder::CanBeLookupTable for GameDistributionTheme {}
|
||||
@@ -836,6 +836,76 @@ pub struct GameDistributionCollection {
|
||||
pub(crate) created_at: Timestamp,
|
||||
}
|
||||
|
||||
/// 平台 / 运营命名的「共创主题」:一棵(或一组)作品树的归组实体。
|
||||
///
|
||||
/// 主题不是作品的属性,而是**运营叙事**:作品在游戏 Tab 里仍作为独立作品展示,主题只是额外
|
||||
/// 的归组维度(一个根可以同时属于多个主题)。归属关系在多对多的 `game_distribution_theme_member`
|
||||
/// 里,因此 `game` 主行(详情页热路径)不挂任何运营字段。
|
||||
///
|
||||
/// `status` 三态 `draft` / `published` / `archived`:公开侧只出现 `published`(
|
||||
/// `module_game_distribution::game_distribution_theme_public_visible`),归档不是删除——成员行
|
||||
/// 保留,只是不再进入公开投影。`created_by_user_id` 只用于审计「谁建的」,不参与鉴权判定。
|
||||
#[spacetimedb::table(
|
||||
accessor = game_distribution_theme,
|
||||
index(
|
||||
accessor = by_game_distribution_theme_created_at,
|
||||
btree(columns = [created_at])
|
||||
),
|
||||
)]
|
||||
#[derive(Clone)]
|
||||
pub struct GameDistributionTheme {
|
||||
/// 平台签发的主题 ID,形如 `theme-*`;由服务端生成,不接受客户端指定。
|
||||
#[primary_key]
|
||||
pub(crate) theme_id: String,
|
||||
/// 主题名(运营命名,不是根作品标题的派生)。
|
||||
pub(crate) name: String,
|
||||
pub(crate) summary: String,
|
||||
/// 角标短文本(本轮用它 + 名称承担「封面」的呈现职责)。
|
||||
pub(crate) badge: String,
|
||||
/// 运营排序权重(成员排序使用)。
|
||||
pub(crate) sort_order: i64,
|
||||
/// `draft` / `published` / `archived`。
|
||||
pub(crate) status: String,
|
||||
/// 创建该主题的运营账号(= 后台会话主体),用于审计,不参与鉴权判定。
|
||||
pub(crate) created_by_user_id: String,
|
||||
pub(crate) created_at: Timestamp,
|
||||
pub(crate) updated_at: Timestamp,
|
||||
}
|
||||
|
||||
/// 主题成员:只允许**根作品**(该作品没有血缘行,即第 0 代)。
|
||||
///
|
||||
/// 主键是确定性构造的 `{theme_id}:{root_game_id}`
|
||||
/// (`module_game_distribution::game_distribution_theme_member_id`):同一主题内同一根在
|
||||
/// **结构上**不可能出现第二行,去重由主键约束本身承担,而不是靠「事务里先查后写」。因此这里
|
||||
/// **不需要** `(theme_id, root_game_id)` 唯一索引;两条具名索引只服务两个真实读取方向
|
||||
/// (主题页按主题取成员、作品详情按根反查所属主题)。
|
||||
///
|
||||
/// 跨主题的同一根会有**多行**(每主题一行),这是预期行为而不是重复数据。作品下架 / 软删除
|
||||
/// **不删除**成员行:读取时按当前公开性过滤(`game_distribution_theme_member_visible`),
|
||||
/// 作品重新公开后成员自动回到主题页。`sort_order` 允许重复,排序由 `member_id` 兜底成全序。
|
||||
#[spacetimedb::table(
|
||||
accessor = game_distribution_theme_member,
|
||||
index(
|
||||
accessor = by_game_distribution_theme_member_theme_id,
|
||||
btree(columns = [theme_id])
|
||||
),
|
||||
index(
|
||||
accessor = by_game_distribution_theme_member_root_game_id,
|
||||
btree(columns = [root_game_id])
|
||||
),
|
||||
)]
|
||||
#[derive(Clone)]
|
||||
pub struct GameDistributionThemeMember {
|
||||
/// 确定性主键 `"{theme_id}:{root_game_id}"`(同 `game_distribution_collection` 的写法)。
|
||||
#[primary_key]
|
||||
pub(crate) member_id: String,
|
||||
pub(crate) theme_id: String,
|
||||
/// 只允许**根作品**。
|
||||
pub(crate) root_game_id: String,
|
||||
pub(crate) sort_order: i64,
|
||||
pub(crate) created_at: Timestamp,
|
||||
}
|
||||
|
||||
/// 游戏发行版本。包摘要、确认字节数和送审资料在创建后作为不可变快照保留;状态和
|
||||
/// 审核/对象安装时间由后续事务推进。
|
||||
#[spacetimedb::table(
|
||||
|
||||
@@ -225,6 +225,10 @@ macro_rules! migration_tables {
|
||||
// 用户对公开作品的收藏(收录):真实用户态投影,随迁移导出/导入;
|
||||
// 作品下架不删除行(读取时按当前公开性过滤,重新公开后自动回来)。
|
||||
game_distribution_collection,
|
||||
// 共创主题与成员:主题是运营命名实体、成员是「主题 ↔ 根作品」的运营归组事实,
|
||||
// 随迁移导出/导入;归档 / 下架只改变公开投影,**不删除成员行**。
|
||||
game_distribution_theme,
|
||||
game_distribution_theme_member,
|
||||
llm_router_account,
|
||||
llm_router_billing_checkpoint,
|
||||
agc_model_catalog,
|
||||
|
||||
Reference in New Issue
Block a user