diff --git a/documentation/THEMES.md b/documentation/THEMES.md index 8bdf5cb..67f605b 100644 --- a/documentation/THEMES.md +++ b/documentation/THEMES.md @@ -80,7 +80,7 @@ When in doubt, pass a single seed color and trust the generator. Only override i You don't need to write light and dark themes separately. The registry expansion does it for you: ```typescript -// game-registry.tsx +// game-game-registry.tsx getAllRegisteredThemeDefinitions() // returns: [ // default-light, default-dark, diff --git a/gulpfile.js b/gulpfile.js index a32f731..8a5d455 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,7 +3,7 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; import { favicons } from "favicons"; import sharp from "sharp"; -import FAVICON_REGISTRY from "./src/registry/favicon-registry.json" with { +import FAVICON_REGISTRY from "./src/game-registry/favicon-registry.json" with { type: "json", }; import IMAGE_SIZES from "#/image-sizes.json" with { diff --git a/prisma/seed.ts b/prisma/seed.ts index 468a1ae..43afeed 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,4 +1,4 @@ -import { allGameDBSeeds } from "#/registry/game-db-seed-registry"; +import { allGameDBSeeds } from "#/game-registry/game-db-seed-registry"; import { auth } from "#/integrations/better-auth/auth"; import { prisma } from "./client"; diff --git a/src/components/AppItemInfoModal.tsx b/src/components/AppItemInfoModal.tsx index 5a79c30..7a932d8 100644 --- a/src/components/AppItemInfoModal.tsx +++ b/src/components/AppItemInfoModal.tsx @@ -24,7 +24,7 @@ import { type WatermarkConfig, } from "#/features/screenshot/ScreenshotContainer.tsx"; import { useScreenshot } from "#/features/screenshot/use-screenshot.ts"; -import { getGameMetadata } from "#/registry/game-public-registry.tsx"; +import { getGameMetadata } from "#/registry/game-public-registry.tsx";; export type AppItemInfoModalProps = { item: AppItem; diff --git a/src/components/GameSwitcher.tsx b/src/components/GameSwitcher.tsx index d3016b9..e78b1d0 100644 --- a/src/components/GameSwitcher.tsx +++ b/src/components/GameSwitcher.tsx @@ -34,7 +34,7 @@ import { getGameLogoComponent, getGameMetadata, REGISTERED_GAME_IDS, -} from "#/registry/game-public-registry.tsx"; +} from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; import classes from "./GameSwitcher.module.css"; diff --git a/src/components/pages/item-list/ItemSearchInput.tsx b/src/components/pages/item-list/ItemSearchInput.tsx index 523cd43..f5eedd0 100644 --- a/src/components/pages/item-list/ItemSearchInput.tsx +++ b/src/components/pages/item-list/ItemSearchInput.tsx @@ -1,7 +1,7 @@ import { Select } from "@mantine/core"; import { useRef, useState } from "react"; import { useGameId } from "#/features/game/use-game-id.ts"; -import { getGameItems } from "#/registry/game-public-registry.tsx"; +import { getGameItems } from "#/registry/game-public-registry.tsx";; export type ItemSearchInputProps = { searchValue: string; diff --git a/src/features/game/active-game.ts b/src/features/game/active-game.ts index 7578bb6..3d51b54 100644 --- a/src/features/game/active-game.ts +++ b/src/features/game/active-game.ts @@ -1,6 +1,6 @@ import { createServerFn } from "@tanstack/react-start"; import { getRequest } from "@tanstack/react-start/server"; -import { getValidatedGameId } from "#/registry/game-public-registry.tsx"; +import { getValidatedGameId } from "#/registry/game-public-registry.tsx";; import { parseCookie, parseSubdomain } from "#/utils.ts"; import type { GameId } from "@/prisma"; diff --git a/src/features/game/data/favorite-games/favorite-games.sync.server.ts b/src/features/game/data/favorite-games/favorite-games.sync.server.ts index c354030..25f524f 100644 --- a/src/features/game/data/favorite-games/favorite-games.sync.server.ts +++ b/src/features/game/data/favorite-games/favorite-games.sync.server.ts @@ -2,11 +2,11 @@ // Split out from favorite-games.server.ts so the sync-replay path lives apart // from the direct CRUD data access. The `.server.ts` suffix opts this into // Start's import protection, keeping prisma out of the client bundle. Consumed -// only by the sync handler registry. +// only by the sync handler game-registry. import { createPresenceToggleSyncHandler } from "#/features/sync/local-data/presence-sync-handler.ts"; import type { SyncHandler } from "#/features/sync/local-data/types.ts"; -import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx"; +import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx";; import { type GameId, prisma } from "@/prisma"; // Self-contained guard (intentionally duplicated from favorite-games.ts) so this diff --git a/src/features/game/data/favorite-games/favorite-games.ts b/src/features/game/data/favorite-games/favorite-games.ts index e9e2672..21c1ab2 100644 --- a/src/features/game/data/favorite-games/favorite-games.ts +++ b/src/features/game/data/favorite-games/favorite-games.ts @@ -11,6 +11,7 @@ import { unfavoriteGame, } from "#/features/game/data/favorite-games/favorite-games.server.ts"; import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx"; + import type { GameId } from "@/prisma"; const GAME_ID_SET = new Set(REGISTERED_GAME_IDS); diff --git a/src/features/game/data/favorite-games/use-favorite-games.ts b/src/features/game/data/favorite-games/use-favorite-games.ts index f9b0dbe..e16b2c5 100644 --- a/src/features/game/data/favorite-games/use-favorite-games.ts +++ b/src/features/game/data/favorite-games/use-favorite-games.ts @@ -13,8 +13,8 @@ import { import { getOrCreateAnonUserId } from "#/features/sync/local-data/identity/anon-id.ts"; import type { LocalUserFavoriteGame } from "#/features/sync/local-data/local/types.ts"; import { enqueueOp } from "#/features/sync/local-data/queue/pending-ops.ts"; +import { getGameMetadata } from "#/registry/game-public-registry.tsx";; import { useSession } from "#/integrations/better-auth/auth-client.ts"; -import { getGameMetadata } from "#/registry/game-public-registry.tsx"; import type { GameId } from "@/prisma"; type FavoriteGameInput = { gameId: GameId }; diff --git a/src/features/game/data/user-profile/use-user-profile-data.ts b/src/features/game/data/user-profile/use-user-profile-data.ts index ff30858..9f4da0b 100644 --- a/src/features/game/data/user-profile/use-user-profile-data.ts +++ b/src/features/game/data/user-profile/use-user-profile-data.ts @@ -24,8 +24,8 @@ import { } from "#/features/game/data/user-profile/user-profile.ts"; import { getOrCreateAnonUserId } from "#/features/sync/local-data/identity/anon-id.ts"; import { enqueueOp } from "#/features/sync/local-data/queue/pending-ops.ts"; +import { getGameMetadata } from "#/registry/game-public-registry.tsx";; import { useSession } from "#/integrations/better-auth/auth-client.ts"; -import { getGameMetadata } from "#/registry/game-public-registry.tsx"; import type { GameId } from "@/prisma"; type GetProfileArgs = { userId?: string } | undefined; diff --git a/src/features/game/data/user-profile/user-profile.server.ts b/src/features/game/data/user-profile/user-profile.server.ts index e4884a8..dadab9d 100644 --- a/src/features/game/data/user-profile/user-profile.server.ts +++ b/src/features/game/data/user-profile/user-profile.server.ts @@ -3,7 +3,7 @@ import { getOptionalUserId, requireUserId, } from "#/features/user/require-user.server.ts"; -import { getGameAvatars } from "#/registry/game-public-registry.tsx"; +import { getGameAvatars } from "#/registry/game-public-registry.tsx";; import { type GameId, prisma } from "@/prisma"; type UpdateAvatarData = { diff --git a/src/features/game/data/user-profile/user-profile.sync.server.ts b/src/features/game/data/user-profile/user-profile.sync.server.ts index b63f44d..52f344a 100644 --- a/src/features/game/data/user-profile/user-profile.sync.server.ts +++ b/src/features/game/data/user-profile/user-profile.sync.server.ts @@ -4,10 +4,10 @@ // than factory-built, because the avatar-override op fans out to two different Prisma // rows (profile primary avatar vs. per-game override) depending on the payload. The // `.server.ts` suffix opts this into Start's import protection, keeping prisma out of -// the client bundle. Consumed only by the sync handler registry. +// the client bundle. Consumed only by the sync handler game-registry. import type { SyncHandler } from "#/features/sync/local-data/types.ts"; -import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx"; +import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx";; import { type GameId, prisma } from "@/prisma"; // Self-contained guard (intentionally duplicated from user-profile.ts) so this diff --git a/src/features/game/data/user-profile/user-profile.ts b/src/features/game/data/user-profile/user-profile.ts index eba9eba..71fb5f9 100644 --- a/src/features/game/data/user-profile/user-profile.ts +++ b/src/features/game/data/user-profile/user-profile.ts @@ -14,7 +14,7 @@ import { updateAvatar, updateProfile, } from "#/features/game/data/user-profile/user-profile.server.ts"; -import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx"; +import { REGISTERED_GAME_IDS } from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; type UserProfileData = { diff --git a/src/features/game/types.ts b/src/features/game/types.ts index b28c12d..2c45653 100644 --- a/src/features/game/types.ts +++ b/src/features/game/types.ts @@ -167,8 +167,13 @@ export type GameConfig< SEARCH_PARAMS: ReturnType | undefined; THEME: ToolkitThemeDefinition | undefined; AVATARS?: GameAvatar[]; - data: GameData; + DATA: GameData; }; +export type PublicGameConfig< + TItem extends AppItem = AppItem, + TCategory extends string | number | symbol = string, +> = Omit, "PAGES" | "DATA">; + // Widened type for runtime-keyed access (base AppItem, string category) export type AnyGameConfig = GameConfig; diff --git a/src/features/sync/local-data/apply-pending-ops.ts b/src/features/sync/local-data/apply-pending-ops.ts index c70f5a2..d4cb734 100644 --- a/src/features/sync/local-data/apply-pending-ops.ts +++ b/src/features/sync/local-data/apply-pending-ops.ts @@ -2,7 +2,7 @@ import { createServerFn } from "@tanstack/react-start"; import { z } from "zod"; import type { SyncResult } from "#/features/sync/local-data/types.ts"; import { requireUserId } from "#/features/user/require-user.server.ts"; -import { syncHandlers } from "#/registry/handler-registry.server.ts"; +import { syncHandlers } from "#/game-registry/handler-registry.server.ts"; /** Re-validates the PendingOp at the server boundary; client data is untrusted. */ const PendingOpSchema = z.object({ diff --git a/src/features/sync/local-data/queue/types.ts b/src/features/sync/local-data/queue/types.ts index 0b7ba51..2b80152 100644 --- a/src/features/sync/local-data/queue/types.ts +++ b/src/features/sync/local-data/queue/types.ts @@ -6,7 +6,7 @@ type PendingOpOperation = "create" | "update" | "upsert" | "delete"; * Human-readable snapshot of a pending op, captured at enqueue time so the * data-sync UI can show the user what each row actually does without parsing * `payload` or the idempotency key. Snapshotted (not derived at render time) - * so an item rename or registry change doesn't rewrite the user's history. + * so an item rename or game-registry change doesn't rewrite the user's history. */ interface PendingOpSummary { /** Primary line, e.g. "Collected: Sword of Legends". */ @@ -44,7 +44,7 @@ interface PendingOp { updatedAt: string; /** The anon user ID at the time the op was enqueued. The user may have logged in since. */ anonUserId: string; - /** Entity name — must match a key in the sync-handler registry. */ + /** Entity name — must match a key in the sync-handler game-registry. */ entity: string; operation: PendingOpOperation; /** The original mutation input, serialized as-is. */ diff --git a/src/features/user/utils.ts b/src/features/user/utils.ts index 29b77f2..d50f216 100644 --- a/src/features/user/utils.ts +++ b/src/features/user/utils.ts @@ -1,5 +1,5 @@ import { clientEnv } from "#/env/client-env.ts"; -import { getGameAvatars } from "#/registry/game-public-registry.tsx"; +import { getGameAvatars } from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; type ResolveAvatarParams = { diff --git a/src/registry/favicon-registry.json b/src/game-registry/favicon-registry.json similarity index 100% rename from src/registry/favicon-registry.json rename to src/game-registry/favicon-registry.json diff --git a/src/registry/game-db-seed-registry.ts b/src/game-registry/game-db-seed-registry.ts similarity index 100% rename from src/registry/game-db-seed-registry.ts rename to src/game-registry/game-db-seed-registry.ts diff --git a/src/registry/game-idb-seed-registry.ts b/src/game-registry/game-idb-seed-registry.ts similarity index 100% rename from src/registry/game-idb-seed-registry.ts rename to src/game-registry/game-idb-seed-registry.ts diff --git a/src/registry/game-pages-registry.tsx b/src/game-registry/game-pages-registry.tsx similarity index 83% rename from src/registry/game-pages-registry.tsx rename to src/game-registry/game-pages-registry.tsx index 5bee0b4..8773173 100644 --- a/src/registry/game-pages-registry.tsx +++ b/src/game-registry/game-pages-registry.tsx @@ -2,14 +2,13 @@ import type { GamePages } from "#/features/game/types.ts"; import { PAGES as CLAIROBSCUR_PAGES } from "#/games/clairobscur/core/game-config/pages.tsx"; import { PAGES as REMNANT2_PAGES } from "#/games/remnant2/core/game-config/pages.tsx"; import { PAGES as SLAYTHESPIRE2_PAGES } from "#/games/slaythespire2/core/game-config/pages.tsx"; - -type GamePagesRegistryGameId = "clairobscur" | "remnant2" | "slaythespire2"; +import type { PublicRegistryGameId } from "#/registry/game-public-registry.tsx"; export const GAME_PAGES_REGISTRY = { clairobscur: CLAIROBSCUR_PAGES, remnant2: REMNANT2_PAGES, slaythespire2: SLAYTHESPIRE2_PAGES, -} satisfies Record; +} satisfies Record; export type GamePagesRegistryGameIdKey = keyof typeof GAME_PAGES_REGISTRY; diff --git a/src/game-registry/game-public-registry.ts b/src/game-registry/game-public-registry.ts new file mode 100644 index 0000000..7282f4d --- /dev/null +++ b/src/game-registry/game-public-registry.ts @@ -0,0 +1,57 @@ +import type { ComponentType } from "react"; +import type { LogoSize } from "#/components/AppLogo.tsx"; +import type { + AnyGameConfig, + GameAvatar, + PublicGameConfig, +} from "#/features/game/types.ts"; +import type { ToolkitThemeDefinition } from "#/features/theme/types.ts"; +import { PUBLIC_GAME_CONFIG as COE33_PUBLIC_GAME_CONFIG } from "#/games/clairobscur/core/game-config"; +import { PUBLIC_GAME_CONFIG as REMNANT2_PUBLIC_GAME_CONFIG } from "#/games/remnant2/core/game-config"; +import { PUBLIC_GAME_CONFIG as SLAYTHESPIRE2_PUBLIC_GAME_CONFIG } from "#/games/slaythespire2/core/game-config"; +import type { GameId } from "@/prisma"; + +// biome-ignore lint/style/useExportsLast: {Needed for derived value} +export const PUBLIC_GAME_REGISTRY = { + clairobscur: COE33_PUBLIC_GAME_CONFIG, + remnant2: REMNANT2_PUBLIC_GAME_CONFIG, + slaythespire2: SLAYTHESPIRE2_PUBLIC_GAME_CONFIG, +} satisfies Record, PublicGameConfig>; + +type PublicRegistryGameId = keyof typeof PUBLIC_GAME_REGISTRY; + +export const REGISTERED_GAME_IDS: readonly PublicRegistryGameId[] = Object.keys( + PUBLIC_GAME_REGISTRY, +) as PublicRegistryGameId[]; + +export const isRegisteredGameId = (id: string): id is PublicRegistryGameId => + id in PUBLIC_GAME_REGISTRY; + +export const getValidatedGameId = (id: string): GameId | undefined => + isRegisteredGameId(id) ? (id as GameId) : undefined; + +// Runtime-keyed getters. Return types are widened to AnyGameConfig's base shapes +// so callers get the usable `AppItem`/`GameMetadata` types rather than the loose +// `unknown`-based PublicGameConfig used only for the `satisfies` check above. +export const getGameMetadata = ( + gameId: string, +): AnyGameConfig["METADATA"] | undefined => + PUBLIC_GAME_REGISTRY[gameId as PublicRegistryGameId]?.METADATA; + +export const getGameItems = ( + gameId: string, +): AnyGameConfig["ITEMS"] | undefined => + PUBLIC_GAME_REGISTRY[gameId as PublicRegistryGameId]?.ITEMS; + +export const getGameTheme = ( + gameId: string, +): ToolkitThemeDefinition | undefined => + PUBLIC_GAME_REGISTRY[gameId as PublicRegistryGameId]?.THEME; + +export const getGameAvatars = (gameId: string): GameAvatar[] | undefined => + PUBLIC_GAME_REGISTRY[gameId as PublicRegistryGameId]?.AVATARS; + +export const getGameLogoComponent = ( + gameId: string, +): ComponentType<{ size?: LogoSize }> | undefined => + PUBLIC_GAME_REGISTRY[gameId as PublicRegistryGameId]?.METADATA?.LogoComponent; diff --git a/src/registry/handler-registry.server.ts b/src/game-registry/handler-registry.server.ts similarity index 90% rename from src/registry/handler-registry.server.ts rename to src/game-registry/handler-registry.server.ts index cf94236..7145811 100644 --- a/src/registry/handler-registry.server.ts +++ b/src/game-registry/handler-registry.server.ts @@ -1,10 +1,10 @@ -// Explicit registry of offline-sync handlers, keyed by entity name. +// Explicit game-registry of offline-sync handlers, keyed by entity name. // // Each entity's handler is imported and listed here by hand — no auto-discovery. // To add a new syncable entity: export its SyncHandler, then add one line below. // applyPendingOpServerFn looks up the handler for an op's `entity` here. // -// Handlers live in per-entity `.server.ts` modules, so this registry is itself +// Handlers live in per-entity `.server.ts` modules, so this game-registry is itself // server-only (the `.server.ts` suffix opts it into Start's import protection). import { favoriteGameSyncHandler } from "#/features/game/data/favorite-games/favorite-games.sync.server.ts"; diff --git a/src/games/clairobscur/core/game-config/index.ts b/src/games/clairobscur/core/game-config/index.ts index 52f10ca..d62a6ad 100644 --- a/src/games/clairobscur/core/game-config/index.ts +++ b/src/games/clairobscur/core/game-config/index.ts @@ -1,19 +1,17 @@ -import type { GameConfig } from "#/features/game/types.ts"; +import type { PublicGameConfig } from "#/features/game/types.ts"; import { ITEMS } from "#/games/clairobscur/core/game-config/items"; import { METADATA } from "#/games/clairobscur/core/game-config/metadata"; -import { PAGES } from "#/games/clairobscur/core/game-config/pages"; import { THEME } from "#/games/clairobscur/core/game-config/theme"; import type { ClairObscurLocalItem } from "#/games/clairobscur/core/types.ts"; -import { clairObscurCollectedItemsData } from "#/games/clairobscur/data/collected-items"; import type { ClairObscurItemCategory } from "@/prisma"; -const GAME_CONFIG = { +export const PUBLIC_GAME_CONFIG: PublicGameConfig< + ClairObscurLocalItem, + ClairObscurItemCategory +> = { ITEMS, THEME, METADATA, - PAGES, SEARCH_PARAMS: undefined, // TODO - data: { collectedItems: clairObscurCollectedItemsData }, -} satisfies GameConfig; - -export { GAME_CONFIG }; + // data: { collectedItems: clairObscurCollectedItemsData }, +}; diff --git a/src/games/clairobscur/data/server/collected-items.sync.server.ts b/src/games/clairobscur/data/server/collected-items.sync.server.ts index fe457cf..ac30027 100644 --- a/src/games/clairobscur/data/server/collected-items.sync.server.ts +++ b/src/games/clairobscur/data/server/collected-items.sync.server.ts @@ -2,7 +2,7 @@ // Split out from collected-items.server.ts so the sync-replay path lives apart // from the direct CRUD data access. The `.server.ts` suffix opts this into // Start's import protection, keeping prisma out of the client bundle. Consumed -// only by the sync handler registry. +// only by the sync handler game-registry. import { createPresenceToggleSyncHandler } from "#/features/sync/local-data/presence-sync-handler.ts"; import type { SyncHandler } from "#/features/sync/local-data/types.ts"; diff --git a/src/games/remnant2/core/game-config/index.ts b/src/games/remnant2/core/game-config/index.ts index 0edd35c..35a3ca1 100644 --- a/src/games/remnant2/core/game-config/index.ts +++ b/src/games/remnant2/core/game-config/index.ts @@ -1,26 +1,19 @@ -import type { GameConfig } from "#/features/game/types.ts"; +import type { PublicGameConfig } from "#/features/game/types.ts"; import { AVATARS } from "#/games/remnant2/core/game-config/avatars"; import { ITEMS } from "#/games/remnant2/core/game-config/items"; import { METADATA } from "#/games/remnant2/core/game-config/metadata"; import { SEARCH_PARAMS } from "#/games/remnant2/core/game-config/nuqs-parsers.ts"; -import { PAGES } from "#/games/remnant2/core/game-config/pages"; import { THEME } from "#/games/remnant2/core/game-config/theme"; import type { Remnant2LocalItem } from "#/games/remnant2/core/types"; -import { remnant2CollectedItemsData } from "#/games/remnant2/data/collected-items"; -import { remnant2CreatedBuildsData } from "#/games/remnant2/data/created-builds"; import type { Remnant2ItemCategory } from "@/prisma"; -const GAME_CONFIG = { +export const PUBLIC_GAME_CONFIG: PublicGameConfig< + Remnant2LocalItem, + Remnant2ItemCategory +> = { ITEMS, THEME, METADATA, - PAGES, SEARCH_PARAMS, AVATARS, - data: { - collectedItems: remnant2CollectedItemsData, - createdBuilds: remnant2CreatedBuildsData, - }, -} satisfies GameConfig; - -export { GAME_CONFIG }; +}; diff --git a/src/games/remnant2/data/server/collected-items.sync.server.ts b/src/games/remnant2/data/server/collected-items.sync.server.ts index 7b52d8e..459a5c9 100644 --- a/src/games/remnant2/data/server/collected-items.sync.server.ts +++ b/src/games/remnant2/data/server/collected-items.sync.server.ts @@ -2,7 +2,7 @@ // Split out from collected-items.server.ts so the sync-replay path lives apart // from the direct CRUD data access. The `.server.ts` suffix opts this into // Start's import protection, keeping prisma out of the client bundle. Consumed -// only by the sync handler registry. +// only by the sync handler game-registry. import { createPresenceToggleSyncHandler } from "#/features/sync/local-data/presence-sync-handler.ts"; import type { SyncHandler } from "#/features/sync/local-data/types.ts"; diff --git a/src/games/slaythespire2/core/game-config/index.ts b/src/games/slaythespire2/core/game-config/index.ts index ee0e416..99eacb9 100644 --- a/src/games/slaythespire2/core/game-config/index.ts +++ b/src/games/slaythespire2/core/game-config/index.ts @@ -1,22 +1,20 @@ -import type { GameConfig } from "#/features/game/types.ts"; +import type { PublicGameConfig } from "#/features/game/types.ts"; import { AVATARS } from "#/games/slaythespire2/core/game-config/avatars"; import { ITEMS } from "#/games/slaythespire2/core/game-config/items"; import { METADATA } from "#/games/slaythespire2/core/game-config/metadata"; import { SEARCH_PARAMS } from "#/games/slaythespire2/core/game-config/nuqs-parsers.ts"; -import { PAGES } from "#/games/slaythespire2/core/game-config/pages"; import { THEME } from "#/games/slaythespire2/core/game-config/theme"; import type { SlayTheSpire2LocalItem } from "#/games/slaythespire2/core/types"; -import { slayTheSpire2CollectedItemsData } from "#/games/slaythespire2/data/collected-items"; import type { SlayTheSpire2ItemCategory } from "@/prisma"; -const GAME_CONFIG = { +export const PUBLIC_GAME_CONFIG: PublicGameConfig< + SlayTheSpire2LocalItem, + SlayTheSpire2ItemCategory +> = { ITEMS, THEME, METADATA, - PAGES, SEARCH_PARAMS, AVATARS, - data: { collectedItems: slayTheSpire2CollectedItemsData }, -} satisfies GameConfig; - -export { GAME_CONFIG }; + // DATA: { collectedItems: slayTheSpire2CollectedItemsData }, +}; diff --git a/src/games/slaythespire2/data/server/collected-items.sync.server.ts b/src/games/slaythespire2/data/server/collected-items.sync.server.ts index 5fb1915..c5b281b 100644 --- a/src/games/slaythespire2/data/server/collected-items.sync.server.ts +++ b/src/games/slaythespire2/data/server/collected-items.sync.server.ts @@ -2,7 +2,7 @@ // Split out from collected-items.server.ts so the sync-replay path lives apart // from the direct CRUD data access. The `.server.ts` suffix opts this into // Start's import protection, keeping prisma out of the client bundle. Consumed -// only by the sync handler registry. +// only by the sync handler game-registry. import { createPresenceToggleSyncHandler } from "#/features/sync/local-data/presence-sync-handler.ts"; import type { SyncHandler } from "#/features/sync/local-data/types.ts"; diff --git a/src/integrations/prisma-idb/idb-seed.ts b/src/integrations/prisma-idb/idb-seed.ts index b1dcdde..e2eac4f 100644 --- a/src/integrations/prisma-idb/idb-seed.ts +++ b/src/integrations/prisma-idb/idb-seed.ts @@ -1,5 +1,5 @@ +import { allGameIDBSeeds } from "#/game-registry/game-idb-seed-registry"; import { getIDBClient } from "#/integrations/prisma-idb/idb-client"; -import { allGameIDBSeeds } from "#/registry/game-idb-seed-registry"; import type { GameId } from "@/prisma"; const LOCAL_USER_ID = "local-user"; diff --git a/src/routes/$gameId/build/$buildId/edit.tsx b/src/routes/$gameId/build/$buildId/edit.tsx index 255dce2..da9edd2 100644 --- a/src/routes/$gameId/build/$buildId/edit.tsx +++ b/src/routes/$gameId/build/$buildId/edit.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; export const Route = createFileRoute("/$gameId/build/$buildId/edit")({ component: function CreateBuildPage() { diff --git a/src/routes/$gameId/build/$buildId/route.tsx b/src/routes/$gameId/build/$buildId/route.tsx index 10ea21b..36e799d 100644 --- a/src/routes/$gameId/build/$buildId/route.tsx +++ b/src/routes/$gameId/build/$buildId/route.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; export const Route = createFileRoute("/$gameId/build/$buildId")({ component: function CreateBuildPage() { diff --git a/src/routes/$gameId/build/create.tsx b/src/routes/$gameId/build/create.tsx index 3cfe678..2df96b4 100644 --- a/src/routes/$gameId/build/create.tsx +++ b/src/routes/$gameId/build/create.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; export const Route = createFileRoute("/$gameId/build/create")({ component: function CreateBuildPage() { diff --git a/src/routes/$gameId/items.tsx b/src/routes/$gameId/items.tsx index 52fdf51..25bdb5a 100644 --- a/src/routes/$gameId/items.tsx +++ b/src/routes/$gameId/items.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; export const Route = createFileRoute("/$gameId/items")({ component: function ItemsPage() { diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 63f7a66..92851ff 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -13,7 +13,7 @@ import { RootDocument } from "#/components/RootDocument.tsx"; import { OG_IMAGE, SERVER_GAME_INPUTS_QUERY_KEY } from "#/constants"; import { clientEnv } from "#/env/client-env.ts"; import { getServerResolvedGameInputsServerFn } from "#/features/game/active-game"; -import { getValidatedGameId } from "#/registry/game-public-registry.tsx"; +import { getValidatedGameId } from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; interface MyRouterContext { diff --git a/src/routes/account/profile/$userId/collected-items.tsx b/src/routes/account/profile/$userId/collected-items.tsx index db81d8a..d4d6c04 100644 --- a/src/routes/account/profile/$userId/collected-items.tsx +++ b/src/routes/account/profile/$userId/collected-items.tsx @@ -5,11 +5,11 @@ import { buildTabHead, loadProfileTabData, } from "#/features/user/profile-tab-head.ts"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; import { getGameMetadata, isRegisteredGameId, -} from "#/registry/game-public-registry.tsx"; +} from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; type CollectedItemsSearch = { diff --git a/src/routes/account/profile/$userId/created-builds.tsx b/src/routes/account/profile/$userId/created-builds.tsx index 2ce23eb..71f715b 100644 --- a/src/routes/account/profile/$userId/created-builds.tsx +++ b/src/routes/account/profile/$userId/created-builds.tsx @@ -6,8 +6,8 @@ import { buildTabHead, loadProfileTabData, } from "#/features/user/profile-tab-head.ts"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; -import { isRegisteredGameId } from "#/registry/game-public-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; +import { isRegisteredGameId } from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; type CreatedBuildsSearch = { diff --git a/src/routes/account/profile/$userId/data-sync.tsx b/src/routes/account/profile/$userId/data-sync.tsx index 388fcb3..b29fa14 100644 --- a/src/routes/account/profile/$userId/data-sync.tsx +++ b/src/routes/account/profile/$userId/data-sync.tsx @@ -27,8 +27,8 @@ import { buildTabHead, loadProfileTabData, } from "#/features/user/profile-tab-head.ts"; +import { getGameMetadata } from "#/registry/game-public-registry.tsx";; import { useSession } from "#/integrations/better-auth/auth-client"; -import { getGameMetadata } from "#/registry/game-public-registry.tsx"; const PendingList = ({ ops, diff --git a/src/routes/account/profile/$userId/route.tsx b/src/routes/account/profile/$userId/route.tsx index df783fc..fbbcdb9 100644 --- a/src/routes/account/profile/$userId/route.tsx +++ b/src/routes/account/profile/$userId/route.tsx @@ -16,7 +16,7 @@ import { import { ProfileHeader } from "#/features/user/ProfileHeader.tsx"; import { ProfileTabNav } from "#/features/user/ProfileTabNav.tsx"; import { resolveAvatar } from "#/features/user/utils.ts"; -import { getValidatedGameId } from "#/registry/game-public-registry.tsx"; +import { getValidatedGameId } from "#/registry/game-public-registry.tsx";; import type { GameId } from "@/prisma"; const ProfileLayout = () => { diff --git a/src/routes/profile/collected-items.tsx b/src/routes/profile/collected-items.tsx index 0f54e92..d6c6e3f 100644 --- a/src/routes/profile/collected-items.tsx +++ b/src/routes/profile/collected-items.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from "@tanstack/react-router"; import { useGameId } from "#/features/game/use-game-id.ts"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; function CollectedItems() { const gameId = useGameId(); diff --git a/src/routes/profile/created-builds.tsx b/src/routes/profile/created-builds.tsx index 73e0a97..7be738b 100644 --- a/src/routes/profile/created-builds.tsx +++ b/src/routes/profile/created-builds.tsx @@ -1,7 +1,7 @@ import { createFileRoute } from "@tanstack/react-router"; import { useGameId } from "#/features/game/use-game-id.ts"; import { ProfileTabPlaceholder } from "#/features/user/ProfileTabPlaceholder.tsx"; -import { getGamePages } from "#/registry/game-pages-registry.tsx"; +import { getGamePages } from "#/game-registry/game-pages-registry.tsx"; function CreatedBuilds() { const gameId = useGameId(); diff --git a/src/utils.ts b/src/utils.ts index 5ff61ad..8198eee 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,5 @@ import { isRegisteredGameId } from "#/registry/game-public-registry.tsx"; + import type { GameId } from "@/prisma"; const ROOT_DOMAINS = ["toolkits.gg", "www.toolkits.gg", "localhost"];