- presets/templates/: 3 light era templates (ww2/present/near-future) + index.json manifest (id, name, year, eraDescription, suggestedPowers, tensions). - server/templates.ts: createTemplateStore (mirror of createPresetStore). - shared/scenario.ts: dependency-free contract for the dynamic scenario path — SuggestedPower / EraTemplate / TemplateMeta / WorldNation / ScenarioEvent / WorldDraft / Checkpoint types, relationFromScore, validateWorldDraft (pure, defensive, never throws), worldDraftToGameState (region-key territory via the injected expand resolver, regionStats seeded, clean turn-1 state). - tests: server/templates.test.ts (manifest order + file shape), server/scenario-shared.test.ts (15 cases: validation/clamp/dedup/null + transform). Fixes #52
29 lines
998 B
TypeScript
29 lines
998 B
TypeScript
// Load era templates for the "Create scenario" path from disk (v0.31.0, #52).
|
|
// Mirrors the preset store (server/presets.ts): each template is a JSON file
|
|
// (presets/templates/<id>.json) and index.json is the lightweight manifest used
|
|
// to render the picker cards. The store is created with the resolved templates
|
|
// directory so it works from repo root (dev) and /app (Docker) alike.
|
|
import { readFileSync } from 'node:fs';
|
|
import type { EraTemplate, TemplateMeta } from '../shared/scenario';
|
|
|
|
export interface TemplateStore {
|
|
listMeta(): TemplateMeta[];
|
|
get(id: string): EraTemplate | null;
|
|
}
|
|
|
|
export function createTemplateStore(dir: string): TemplateStore {
|
|
const manifest = JSON.parse(readFileSync(`${dir}/index.json`, 'utf8')) as TemplateMeta[];
|
|
return {
|
|
listMeta() {
|
|
return manifest;
|
|
},
|
|
get(id: string) {
|
|
try {
|
|
return JSON.parse(readFileSync(`${dir}/${id}.json`, 'utf8')) as EraTemplate;
|
|
} catch {
|
|
return null;
|
|
}
|
|
},
|
|
};
|
|
}
|