deadhead-space-freight-tycoon/packages/schema/src/routes.ts

315 lines
8.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"]>;