315 lines
8.2 KiB
TypeScript
315 lines
8.2 KiB
TypeScript
import type { z } from "zod";
|
||
import { playerStateSchema, serverTimeSchema } from "./entities";
|
||
import {
|
||
acknowledgeSummariesRequestSchema,
|
||
acknowledgeSummariesResponseSchema,
|
||
assignPilotRequestSchema,
|
||
bayResponseSchema,
|
||
buyShipRequestSchema,
|
||
claimGoalRequestSchema,
|
||
companyResponseSchema,
|
||
contractBoardRequestSchema,
|
||
contractBoardResponseSchema,
|
||
createDispatchRequestSchema,
|
||
createGuestResponseSchema,
|
||
devAddCreditsRequestSchema,
|
||
devAdvanceClockRequestSchema,
|
||
devAdvanceClockResponseSchema,
|
||
devPilotRequestSchema,
|
||
devShipRequestSchema,
|
||
dispatchOfficeResponseSchema,
|
||
dispatchResponseSchema,
|
||
emergencyFuelRequestSchema,
|
||
emptyRequestSchema,
|
||
exportSaveResponseSchema,
|
||
hirePilotRequestSchema,
|
||
importSaveRequestSchema,
|
||
leaseBayRequestSchema,
|
||
pilotModeRequestSchema,
|
||
pilotOrdersRequestSchema,
|
||
pilotResponseSchema,
|
||
refuelPolicyRequestSchema,
|
||
refuelRequestSchema,
|
||
renameCompanyRequestSchema,
|
||
repayLoanRequestSchema,
|
||
restPilotRequestSchema,
|
||
shipResponseSchema,
|
||
spendSkillPointRequestSchema,
|
||
spendingFloorRequestSchema,
|
||
startUpgradeRequestSchema,
|
||
unassignPilotRequestSchema,
|
||
} from "./requests";
|
||
|
||
export interface RouteDef {
|
||
method: "GET" | "POST";
|
||
/** Under `/api` (decision 0.5.20). `:name` segments are path parameters. */
|
||
path: string;
|
||
/** Path parameters plus body: every `:name` in the path is a field here. */
|
||
request: z.ZodType;
|
||
/** Body of the 2xx response. Errors always use `errorResponseSchema`. */
|
||
response: z.ZodType;
|
||
/** Whether it needs a company (was: a session, before CR-014). */
|
||
auth: boolean;
|
||
}
|
||
|
||
/** Every endpoint of the base game: the contract between server and client. */
|
||
export const routes = {
|
||
getServerTime: {
|
||
method: "GET",
|
||
path: "/api/time",
|
||
request: emptyRequestSchema,
|
||
response: serverTimeSchema,
|
||
auth: false,
|
||
},
|
||
createGuest: {
|
||
method: "POST",
|
||
path: "/api/guest",
|
||
request: emptyRequestSchema,
|
||
response: createGuestResponseSchema,
|
||
auth: false,
|
||
},
|
||
getPlayerState: {
|
||
method: "GET",
|
||
path: "/api/state",
|
||
request: emptyRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
getContractBoard: {
|
||
method: "GET",
|
||
path: "/api/locations/:locationId/board",
|
||
request: contractBoardRequestSchema,
|
||
response: contractBoardResponseSchema,
|
||
auth: true,
|
||
},
|
||
getTutorialBoard: {
|
||
method: "GET",
|
||
path: "/api/tutorial/board",
|
||
request: emptyRequestSchema,
|
||
response: contractBoardResponseSchema,
|
||
auth: true,
|
||
},
|
||
createDispatch: {
|
||
method: "POST",
|
||
path: "/api/dispatches",
|
||
request: createDispatchRequestSchema,
|
||
response: dispatchResponseSchema,
|
||
auth: true,
|
||
},
|
||
buyShip: {
|
||
method: "POST",
|
||
path: "/api/ships",
|
||
request: buyShipRequestSchema,
|
||
response: shipResponseSchema,
|
||
auth: true,
|
||
},
|
||
startUpgrade: {
|
||
method: "POST",
|
||
path: "/api/ships/:shipId/upgrades",
|
||
request: startUpgradeRequestSchema,
|
||
response: shipResponseSchema,
|
||
auth: true,
|
||
},
|
||
/** CR-015: fill the tank (or buy `amountFu`) at the ship's location. */
|
||
refuelShip: {
|
||
method: "POST",
|
||
path: "/api/ships/:shipId/refuel",
|
||
request: refuelRequestSchema,
|
||
response: shipResponseSchema,
|
||
auth: true,
|
||
},
|
||
setRefuelPolicy: {
|
||
method: "POST",
|
||
path: "/api/ships/:shipId/refuel-policy",
|
||
request: refuelPolicyRequestSchema,
|
||
response: shipResponseSchema,
|
||
auth: true,
|
||
},
|
||
/** CR-015: fuel for the cheapest way out, added to the loan (decision 0.5.99). */
|
||
orderEmergencyFuel: {
|
||
method: "POST",
|
||
path: "/api/ships/:shipId/emergency-fuel",
|
||
request: emergencyFuelRequestSchema,
|
||
response: shipResponseSchema,
|
||
auth: true,
|
||
},
|
||
leaseBay: {
|
||
method: "POST",
|
||
path: "/api/bays",
|
||
request: leaseBayRequestSchema,
|
||
response: bayResponseSchema,
|
||
auth: true,
|
||
},
|
||
hirePilot: {
|
||
method: "POST",
|
||
path: "/api/pilots",
|
||
request: hirePilotRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
assignPilot: {
|
||
method: "POST",
|
||
path: "/api/pilots/:pilotId/assign",
|
||
request: assignPilotRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
unassignPilot: {
|
||
method: "POST",
|
||
path: "/api/pilots/:pilotId/unassign",
|
||
request: unassignPilotRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
restPilot: {
|
||
method: "POST",
|
||
path: "/api/pilots/:pilotId/rest",
|
||
request: restPilotRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
spendSkillPoint: {
|
||
method: "POST",
|
||
path: "/api/pilots/:pilotId/skills",
|
||
request: spendSkillPointRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
/** CR-021: Independent pilots (decisions 0.5.123–0.5.127). */
|
||
buyDispatchOffice: {
|
||
method: "POST",
|
||
path: "/api/company/dispatch-office",
|
||
request: emptyRequestSchema,
|
||
response: dispatchOfficeResponseSchema,
|
||
auth: true,
|
||
},
|
||
setPilotMode: {
|
||
method: "POST",
|
||
path: "/api/pilots/:pilotId/mode",
|
||
request: pilotModeRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
setPilotOrders: {
|
||
method: "POST",
|
||
path: "/api/pilots/:pilotId/orders",
|
||
request: pilotOrdersRequestSchema,
|
||
response: pilotResponseSchema,
|
||
auth: true,
|
||
},
|
||
setSpendingFloor: {
|
||
method: "POST",
|
||
path: "/api/company/spending-floor",
|
||
request: spendingFloorRequestSchema,
|
||
response: dispatchOfficeResponseSchema,
|
||
auth: true,
|
||
},
|
||
acknowledgeSummaries: {
|
||
method: "POST",
|
||
path: "/api/summaries/acknowledge",
|
||
request: acknowledgeSummariesRequestSchema,
|
||
response: acknowledgeSummariesResponseSchema,
|
||
auth: true,
|
||
},
|
||
/** CR-022: the welcome cards are closed for this company (decision 0.5.131). */
|
||
markWelcomeSeen: {
|
||
method: "POST",
|
||
path: "/api/welcome/seen",
|
||
request: emptyRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
acceptDeal: {
|
||
method: "POST",
|
||
path: "/api/deal/accept",
|
||
request: emptyRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
/** On the device only (CR-014): the save as an export code. */
|
||
exportSave: {
|
||
method: "GET",
|
||
path: "/api/save/export",
|
||
request: emptyRequestSchema,
|
||
response: exportSaveResponseSchema,
|
||
auth: true,
|
||
},
|
||
/** On the device only (CR-014): replaces this device's company with an exported one. */
|
||
importSave: {
|
||
method: "POST",
|
||
path: "/api/save/import",
|
||
request: importSaveRequestSchema,
|
||
response: createGuestResponseSchema,
|
||
auth: false,
|
||
},
|
||
/** Non-production only (CR-011): not registered when NODE_ENV is production. */
|
||
devAdvanceClock: {
|
||
method: "POST",
|
||
path: "/api/test/advance-clock",
|
||
request: devAdvanceClockRequestSchema,
|
||
response: devAdvanceClockResponseSchema,
|
||
auth: true,
|
||
},
|
||
devAddCredits: {
|
||
method: "POST",
|
||
path: "/api/test/add-credits",
|
||
request: devAddCreditsRequestSchema,
|
||
response: companyResponseSchema,
|
||
auth: true,
|
||
},
|
||
devPilot: {
|
||
method: "POST",
|
||
path: "/api/test/pilot",
|
||
request: devPilotRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
devShip: {
|
||
method: "POST",
|
||
path: "/api/test/ship",
|
||
request: devShipRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
devDiscoverAll: {
|
||
method: "POST",
|
||
path: "/api/test/discover-all",
|
||
request: emptyRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
newCompany: {
|
||
method: "POST",
|
||
path: "/api/company/new",
|
||
request: emptyRequestSchema,
|
||
response: playerStateSchema,
|
||
auth: true,
|
||
},
|
||
renameCompany: {
|
||
method: "POST",
|
||
path: "/api/company/name",
|
||
request: renameCompanyRequestSchema,
|
||
response: companyResponseSchema,
|
||
auth: true,
|
||
},
|
||
repayLoan: {
|
||
method: "POST",
|
||
path: "/api/loan/repay",
|
||
request: repayLoanRequestSchema,
|
||
response: companyResponseSchema,
|
||
auth: true,
|
||
},
|
||
claimGoal: {
|
||
method: "POST",
|
||
path: "/api/goals/:goalId/claim",
|
||
request: claimGoalRequestSchema,
|
||
response: companyResponseSchema,
|
||
auth: true,
|
||
},
|
||
} as const satisfies Record<string, RouteDef>;
|
||
|
||
export type Routes = typeof routes;
|
||
export type RouteName = keyof Routes;
|
||
export type RouteRequest<N extends RouteName> = z.input<Routes[N]["request"]>;
|
||
export type RouteResponse<N extends RouteName> = z.output<Routes[N]["response"]>;
|