feat: Add Games (#276)

## Description
<!-- Briefly describe the purpose and scope of your changes -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced comprehensive management of game libraries, including
adding, removing, and listing games in a user's Steam library.
- Added new API endpoints for retrieving detailed game information by ID
and listing all games in a user's library.
- Enabled friend-related API endpoints to list friends and fetch friend
details by SteamID.
- Added category and base game data structures with validation and
serialization for enriched game metadata.
- Introduced ownership update functionality for Steam accounts during
login.
- Added new game and category linking to support detailed game metadata
and categorization.
- Introduced member retrieval functions for enhanced team and user
management.

- **Improvements**
- Enhanced authentication to enforce team membership checks and provide
member-level access control.
- Improved Steam account ownership handling to ensure accurate user
association.
  - Added indexes to friend relationships for optimized querying.
  - Refined API routing structure with added game and friend routes.
- Improved friend listing queries for efficiency and data completeness.

- **Bug Fixes**
  - Fixed formatting issues in permissions related to Steam accounts.

- **Other**
- Refined event handling for user account refresh based on user ID
instead of email.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Wanjohi
2025-05-10 08:11:00 +03:00
committed by GitHub
parent d933c1e61d
commit 0b995fa540
23 changed files with 1120 additions and 142 deletions

View File

@@ -142,50 +142,26 @@ export namespace Steam {
}),
);
// TODO: This needs to be handled better, as it has the potential to turn unnecessary fields into `null`
// export const update = fn(
// Info
// .extend({
// useUser: z.boolean(),
// })
// .partial({
// useUser: true,
// userID: true,
// status: true,
// name: true,
// lastSyncedAt: true,
// avatarHash: true,
// username: true,
// realName: true,
// limitations: true,
// profileUrl: true,
// steamMemberSince: true,
// }),
// async (input) =>
// useTransaction(async (tx) => {
// const userID = typeof input.userID === "string" ? input.userID : input.useUser ? Actor.userID() : undefined;
// await tx
// .update(steamTable)
// .set({
// userID,
// id: input.id,
// name: input.name,
// realName: input.realName,
// profileUrl: input.profileUrl,
// avatarHash: input.avatarHash,
// limitations: input.limitations,
// status: input.status ?? "offline",
// username: input.username ?? "unknown",
// steamMemberSince: input.steamMemberSince,
// lastSyncedAt: input.lastSyncedAt ?? Common.utc(),
// })
// .where(eq(steamTable.id, input.id));
// await afterTx(async () =>
// bus.publish(Resource.Bus, Events.Updated, { userID: userID ?? null, steamID: input.id })
// );
// })
// )
export const updateOwner = fn(
z
.object({
userID: z.string(),
steamID: z.string()
})
.partial({
userID: true
}),
(input) =>
useTransaction(async (tx) => {
const userID = input.userID ?? Actor.userID()
await tx
.update(steamTable)
.set({
userID
})
.where(eq(steamTable.id, input.steamID));
})
)
export const fromUserID = fn(
z.string().min(1),