feat: v0.6.0 — data foundation: Drizzle ORM + SQLite (sql.js/WASM) persistence, first-run seed, read-only GET /api/state snapshot
This commit is contained in:
+110
-1
@@ -8,7 +8,7 @@ export const openApiSpec = {
|
||||
info: {
|
||||
title: 'Flight Ops API',
|
||||
description:
|
||||
'JSON API for Flight Ops — EU airport data for the map, plus app metadata.',
|
||||
'JSON API for Flight Ops — EU airport data for the map, the live game-state snapshot, and app metadata.',
|
||||
// Sourced from package.json so it stays in sync with every version bump.
|
||||
version: pkg.version,
|
||||
},
|
||||
@@ -33,6 +33,24 @@ export const openApiSpec = {
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/state': {
|
||||
get: {
|
||||
summary: 'Game state snapshot',
|
||||
description:
|
||||
'Full current game state for client polling — account, sim clock, planes and contracts. Read-only.',
|
||||
operationId: 'getState',
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Current game state',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: { $ref: '#/components/schemas/StateSnapshot' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/version': {
|
||||
get: {
|
||||
summary: 'App version',
|
||||
@@ -104,6 +122,97 @@ export const openApiSpec = {
|
||||
},
|
||||
required: ['name', 'icao', 'lat', 'lon'],
|
||||
},
|
||||
StateSnapshot: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
account: { $ref: '#/components/schemas/AccountState' },
|
||||
simState: { $ref: '#/components/schemas/SimState' },
|
||||
planes: {
|
||||
type: 'array',
|
||||
items: { $ref: '#/components/schemas/PlaneState' },
|
||||
},
|
||||
contracts: {
|
||||
type: 'array',
|
||||
items: { $ref: '#/components/schemas/ContractState' },
|
||||
},
|
||||
},
|
||||
required: ['account', 'simState', 'planes', 'contracts'],
|
||||
},
|
||||
AccountState: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
cash: { type: 'number' },
|
||||
reputation: { type: 'number' },
|
||||
},
|
||||
required: ['cash', 'reputation'],
|
||||
},
|
||||
SimState: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
clockMs: { type: 'integer', description: 'Sim-clock epoch ms (game time)' },
|
||||
timeScale: { type: 'number', minimum: 1, maximum: 60 },
|
||||
paused: { type: 'boolean' },
|
||||
},
|
||||
required: ['clockMs', 'timeScale', 'paused'],
|
||||
},
|
||||
PlaneState: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
model: { type: 'string' },
|
||||
status: { enum: ['available', 'flying'] },
|
||||
fuel: { type: 'number' },
|
||||
maxFuel: { type: 'number' },
|
||||
locationIcao: { type: 'string' },
|
||||
locationName: { type: 'string' },
|
||||
contractId: { type: ['string', 'null'] },
|
||||
lat: { type: 'number' },
|
||||
lon: { type: 'number' },
|
||||
},
|
||||
required: [
|
||||
'id',
|
||||
'model',
|
||||
'status',
|
||||
'fuel',
|
||||
'maxFuel',
|
||||
'locationIcao',
|
||||
'locationName',
|
||||
'contractId',
|
||||
'lat',
|
||||
'lon',
|
||||
],
|
||||
},
|
||||
ContractState: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
originIcao: { type: 'string' },
|
||||
originName: { type: 'string' },
|
||||
destIcao: { type: 'string' },
|
||||
destName: { type: 'string' },
|
||||
reward: { type: 'number' },
|
||||
cargoType: { type: 'string' },
|
||||
cargoCount: { type: 'integer' },
|
||||
deadlineSimTime: { type: 'integer', description: 'Sim-clock epoch ms (game time)' },
|
||||
status: { enum: ['open', 'accepted', 'completed'] },
|
||||
planeId: { type: ['string', 'null'] },
|
||||
createdSimTime: { type: 'integer' },
|
||||
},
|
||||
required: [
|
||||
'id',
|
||||
'originIcao',
|
||||
'originName',
|
||||
'destIcao',
|
||||
'destName',
|
||||
'reward',
|
||||
'cargoType',
|
||||
'cargoCount',
|
||||
'deadlineSimTime',
|
||||
'status',
|
||||
'planeId',
|
||||
'createdSimTime',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user