From b1f2523fa34719ab3fdf9b14f997fd9c6ccf949f Mon Sep 17 00:00:00 2001 From: Hide_D Date: Mon, 5 Jan 2026 15:13:59 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20GamePrisma=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=ED=81=B4=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EC=96=B8=ED=8A=B8=20=EB=B0=8F=20=EA=B4=80=EB=A0=A8=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=A0=95=EC=9D=98=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/game-api/src/context.ts | 123 +++--------------------- app/game-api/src/turns/reservedTurns.ts | 9 +- app/game-api/test/reservedTurns.test.ts | 20 ++-- app/gateway-api/src/index.ts | 5 + app/gateway-frontend/src/utils/trpc.ts | 2 +- app/gateway-frontend/tsconfig.json | 4 +- packages/infra/src/db.ts | 100 +++---------------- 7 files changed, 47 insertions(+), 216 deletions(-) diff --git a/app/game-api/src/context.ts b/app/game-api/src/context.ts index 6ea53d8..161e914 100644 --- a/app/game-api/src/context.ts +++ b/app/game-api/src/context.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; import type { GameSessionTokenPayload } from '@sammo-ts/common'; -import type { DatabaseClient as InfraDatabaseClient, RedisConnector } from '@sammo-ts/infra'; +import type { DatabaseClient as InfraDatabaseClient, RedisConnector, GamePrisma } from '@sammo-ts/infra'; import type { TurnDaemonTransport } from './daemon/transport.js'; import type { BattleSimTransport } from './battleSim/transport.js'; @@ -26,119 +26,18 @@ export const zWorldStateMeta = z.object({ }); export type WorldStateMeta = z.infer; -export interface WorldStateRow { - scenarioCode: string; - currentYear: number; - currentMonth: number; - tickSeconds: number; - config: unknown; - meta: unknown; - updatedAt: Date; -} +export type WorldStateRow = GamePrisma.WorldStateGetPayload<{}>; +export type GeneralRow = GamePrisma.GeneralGetPayload<{}>; +export type GeneralTurnRow = GamePrisma.GeneralTurnGetPayload<{}>; +export type NationTurnRow = GamePrisma.NationTurnGetPayload<{}>; +export type CityRow = GamePrisma.CityGetPayload<{}>; +export type NationRow = GamePrisma.NationGetPayload<{}>; +export type TroopRow = GamePrisma.TroopGetPayload<{}>; -export interface GeneralRow { - id: number; - userId: string | null; - name: string; - nationId: number; - cityId: number; - troopId: number; - leadership: number; - strength: number; - intel: number; - experience: number; - dedication: number; - officerLevel: number; - personalCode: string; - specialCode: string; - special2Code: string; - horseCode: string; - weaponCode: string; - bookCode: string; - itemCode: string; - injury: number; - gold: number; - rice: number; - crew: number; - crewTypeId: number; - train: number; - atmos: number; - age: number; - npcState: number; - picture: string | null; - meta: unknown; -} +export type JsonValue = GamePrisma.JsonValue; +export type InputJsonValue = GamePrisma.InputJsonValue; -export interface GeneralTurnRow { - id: number; - generalId: number; - turnIdx: number; - actionCode: string; - arg: unknown; -} - -export interface NationTurnRow { - id: number; - nationId: number; - officerLevel: number; - turnIdx: number; - actionCode: string; - arg: unknown; -} - -export interface CityRow { - id: number; - name: string; - nationId: number; - level: number; - population: number; - populationMax: number; - agriculture: number; - agricultureMax: number; - commerce: number; - commerceMax: number; - security: number; - securityMax: number; - trust: number; - trade: number; - supplyState: number; - frontState: number; - defence: number; - defenceMax: number; - wall: number; - wallMax: number; - region: number; - meta: unknown; -} - -export interface NationRow { - id: number; - name: string; - color: string; - capitalCityId: number | null; - gold: number; - rice: number; - tech: number; - level: number; - typeCode: string; - meta: unknown; -} - -export interface TroopRow { - troopLeaderId: number; - nationId: number; - name: string; -} - -export type DatabaseClient = InfraDatabaseClient< - WorldStateRow, - GeneralRow, - CityRow, - NationRow, - GeneralTurnRow, - NationTurnRow, - TroopRow ->; +export type DatabaseClient = InfraDatabaseClient; export interface GameApiContext { db: DatabaseClient; diff --git a/app/game-api/src/turns/reservedTurns.ts b/app/game-api/src/turns/reservedTurns.ts index 5d15b59..f3e22a1 100644 --- a/app/game-api/src/turns/reservedTurns.ts +++ b/app/game-api/src/turns/reservedTurns.ts @@ -2,6 +2,7 @@ import type { DatabaseClient, GeneralTurnRow, NationTurnRow, + InputJsonValue, } from '../context.js'; export const DEFAULT_TURN_ACTION = '휴식'; @@ -10,13 +11,13 @@ export const MAX_NATION_TURNS = 12; export interface ReservedTurnEntry { action: string; - args: Record; + args: InputJsonValue; } export interface ReservedTurnView { index: number; action: string; - args: Record; + args: InputJsonValue; } const isRecord = (value: unknown): value is Record => @@ -25,8 +26,8 @@ const isRecord = (value: unknown): value is Record => const normalizeAction = (action: string | null | undefined): string => action && action.length > 0 ? action : DEFAULT_TURN_ACTION; -const normalizeArgs = (args: unknown): Record => - isRecord(args) ? args : {}; +const normalizeArgs = (args: unknown): InputJsonValue => + isRecord(args) ? (args as InputJsonValue) : {}; const createDefaultEntry = (): ReservedTurnEntry => ({ action: DEFAULT_TURN_ACTION, diff --git a/app/game-api/test/reservedTurns.test.ts b/app/game-api/test/reservedTurns.test.ts index 0353b33..4fd1962 100644 --- a/app/game-api/test/reservedTurns.test.ts +++ b/app/game-api/test/reservedTurns.test.ts @@ -18,7 +18,7 @@ const buildDb = () => { const generalTurns = new Map(); const nationTurns = new Map(); - const db: DatabaseClient = { + const db = { worldState: { findFirst: async () => null, }, @@ -32,13 +32,13 @@ const buildDb = () => { findUnique: async () => null, }, generalTurn: { - findMany: async ({ where }) => generalTurns.get(where.generalId) ?? [], - deleteMany: async ({ where }) => { + findMany: async ({ where }: any) => generalTurns.get(where.generalId) ?? [], + deleteMany: async ({ where }: any) => { generalTurns.delete(where.generalId); return {}; }, - createMany: async ({ data }) => { - const rows = data.map((row, index) => ({ + createMany: async ({ data }: any) => { + const rows = data.map((row: any, index: number) => ({ id: index + 1, generalId: row.generalId, turnIdx: row.turnIdx, @@ -53,14 +53,14 @@ const buildDb = () => { }, }, nationTurn: { - findMany: async ({ where }) => + findMany: async ({ where }: any) => nationTurns.get(`${where.nationId}:${where.officerLevel}`) ?? [], - deleteMany: async ({ where }) => { + deleteMany: async ({ where }: any) => { nationTurns.delete(`${where.nationId}:${where.officerLevel}`); return {}; }, - createMany: async ({ data }) => { - const rows = data.map((row, index) => ({ + createMany: async ({ data }: any) => { + const rows = data.map((row: any, index: number) => ({ id: index + 1, nationId: row.nationId, officerLevel: row.officerLevel, @@ -76,7 +76,7 @@ const buildDb = () => { return {}; }, }, - }; + } as unknown as DatabaseClient; return { db }; }; diff --git a/app/gateway-api/src/index.ts b/app/gateway-api/src/index.ts index 40ab679..5c2a210 100644 --- a/app/gateway-api/src/index.ts +++ b/app/gateway-api/src/index.ts @@ -8,6 +8,11 @@ export * from './config.js'; export * from './context.js'; export * from './router.js'; export * from './server.js'; +export { GatewayPrisma } from '@sammo-ts/infra'; +export type JsonObject = GatewayPrisma.JsonObject; +export type JsonArray = GatewayPrisma.JsonArray; +export * from './orchestrator/profileRepository.js'; +export * from './orchestrator/gatewayOrchestrator.js'; export * from './auth/userRepository.js'; export * from './auth/passwordHasher.js'; export * from './auth/inMemoryUserRepository.js'; diff --git a/app/gateway-frontend/src/utils/trpc.ts b/app/gateway-frontend/src/utils/trpc.ts index 3e92dd4..71ba605 100644 --- a/app/gateway-frontend/src/utils/trpc.ts +++ b/app/gateway-frontend/src/utils/trpc.ts @@ -1,5 +1,5 @@ import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'; -import type { AppRouter } from '../../../gateway-api/src/router'; +import type { AppRouter } from '@sammo-ts/gateway-api'; const getSessionToken = (): string | null => { if (typeof window === 'undefined') { diff --git a/app/gateway-frontend/tsconfig.json b/app/gateway-frontend/tsconfig.json index 4d9994f..d3869ba 100644 --- a/app/gateway-frontend/tsconfig.json +++ b/app/gateway-frontend/tsconfig.json @@ -33,7 +33,9 @@ "@sammo-ts/game-engine": ["../../app/game-engine/src/index.ts"], "@sammo-ts/game-engine/*": ["../../app/game-engine/src/*"], "@sammo-ts/game-api": ["../../app/game-api/src/index.ts"], - "@sammo-ts/game-api/*": ["../../app/game-api/src/*"] + "@sammo-ts/game-api/*": ["../../app/game-api/src/*"], + "@sammo-ts/gateway-api": ["../../app/gateway-api/src/index.ts"], + "@sammo-ts/gateway-api/*": ["../../app/gateway-api/src/*"] } }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], diff --git a/packages/infra/src/db.ts b/packages/infra/src/db.ts index bb6823c..d18fe68 100644 --- a/packages/infra/src/db.ts +++ b/packages/infra/src/db.ts @@ -1,89 +1,13 @@ -export interface DatabaseClient< - WorldStateRow = unknown, - GeneralRow = unknown, - CityRow = unknown, - NationRow = unknown, - GeneralTurnRow = unknown, - NationTurnRow = unknown, - TroopRow = unknown -> { - $transaction( - queries: Array> - ): Promise; - $queryRaw( - query: TemplateStringsArray, - ...values: unknown[] - ): Promise; - worldState: { - findFirst(args?: unknown): Promise; - }; - general: { - findUnique(args: { where: { id: number } }): Promise; - findFirst(args: { - where: { userId?: string; npcState?: number | { gt: number } }; - select?: { name?: boolean; picture?: boolean }; - }): Promise; - findMany(args: { - where?: { nationId?: number }; - }): Promise; - count(args?: { - where?: { npcState?: number | { gt: number } }; - }): Promise; - update(args: { - where: { id: number }; - data: Partial; - }): Promise; - updateMany(args: { - where: { troopId?: number }; - data: Partial; - }): Promise; - }; - city: { - findUnique(args: { where: { id: number } }): Promise; - }; - nation: { - findUnique(args: { where: { id: number } }): Promise; - count(args?: { where?: { level?: { gt: number } } }): Promise; - }; - generalTurn: { - findMany(args: { - where: { generalId: number }; - orderBy?: { turnIdx: 'asc' | 'desc' }[]; - }): Promise; - deleteMany(args: { where: { generalId: number } }): Promise; - createMany(args: { - data: Array<{ - generalId: number; - turnIdx: number; - actionCode: string; - arg: unknown; - }>; - }): Promise; - }; - nationTurn: { - findMany(args: { - where: { nationId: number; officerLevel: number }; - orderBy?: { turnIdx: 'asc' | 'desc' }[]; - }): Promise; - deleteMany(args: { - where: { nationId: number; officerLevel: number }; - }): Promise; - createMany(args: { - data: Array<{ - nationId: number; - officerLevel: number; - turnIdx: number; - actionCode: string; - arg: unknown; - }>; - }): Promise; - }; - troop: { - findUnique(args: { - where: { troopLeaderId: number }; - }): Promise; - deleteMany(args: { - where: { troopLeaderId: number }; - }): Promise; - }; +import type { GamePrisma, GamePrismaClient } from './gamePrisma.js'; + +export interface DatabaseClient { + $transaction: GamePrismaClient['$transaction']; + $queryRaw: GamePrismaClient['$queryRaw']; + worldState: GamePrisma.WorldStateDelegate; + general: GamePrisma.GeneralDelegate; + city: GamePrisma.CityDelegate; + nation: GamePrisma.NationDelegate; + generalTurn: GamePrisma.GeneralTurnDelegate; + nationTurn: GamePrisma.NationTurnDelegate; + troop: GamePrisma.TroopDelegate; }