fix: 내부 전용 예약 명령 실행 경계를 분리한다

This commit is contained in:
2026-08-24 16:02:35 +00:00
parent b5763290d2
commit 9fe1f1878a
11 changed files with 169 additions and 63 deletions
@@ -1,10 +1,14 @@
import { GENERAL_TURN_COMMAND_KEYS, isGeneralTurnCommandKey, type GeneralTurnCommandKey } from './general/index.js';
import {
SELECTABLE_GENERAL_TURN_COMMAND_KEYS,
isSelectableGeneralTurnCommandKey,
type SelectableGeneralTurnCommandKey,
} from './general/index.js';
import { NATION_TURN_COMMAND_KEYS, isNationTurnCommandKey, type NationTurnCommandKey } from './nation/index.js';
import { asStringArray, isRecord } from '@sammo-ts/common';
import { TurnCommandProfileInputSchema } from '../../resources/turnCommandSchema.js';
export interface TurnCommandProfile {
general: GeneralTurnCommandKey[];
general: SelectableGeneralTurnCommandKey[];
nation: NationTurnCommandKey[];
}
@@ -15,7 +19,7 @@ export interface TurnCommandGroup<Key extends string> {
export interface ScenarioTurnCommandProfileResolution {
profile: TurnCommandProfile;
generalGroups: Array<TurnCommandGroup<GeneralTurnCommandKey>> | null;
generalGroups: Array<TurnCommandGroup<SelectableGeneralTurnCommandKey>> | null;
nationGroups: Array<TurnCommandGroup<NationTurnCommandKey>> | null;
}
@@ -49,7 +53,7 @@ const parseKeyList = <T extends string>(options: {
};
export const DEFAULT_TURN_COMMAND_PROFILE: TurnCommandProfile = {
general: [...GENERAL_TURN_COMMAND_KEYS],
general: [...SELECTABLE_GENERAL_TURN_COMMAND_KEYS],
nation: [...NATION_TURN_COMMAND_KEYS],
};
@@ -62,7 +66,7 @@ export const parseTurnCommandProfile = (raw: unknown): TurnCommandProfile => {
return {
general: parseKeyList({
raw: data.general,
isKey: isGeneralTurnCommandKey,
isKey: isSelectableGeneralTurnCommandKey,
label: 'general',
}),
nation: parseKeyList({
@@ -133,7 +137,7 @@ export const resolveScenarioTurnCommandProfile = (
const config = isRecord(scenarioConst) ? scenarioConst : {};
const generalGroups = parseScenarioCommandGroups({
raw: config.availableGeneralCommand,
isKey: isGeneralTurnCommandKey,
isKey: isSelectableGeneralTurnCommandKey,
label: 'general',
});
const nationGroups = parseScenarioCommandGroups({
@@ -60,6 +60,21 @@ export const GENERAL_TURN_COMMAND_KEYS = [
export type GeneralTurnCommandKey = (typeof GENERAL_TURN_COMMAND_KEYS)[number];
/**
* 엔진·서신·월간 이벤트만 생성할 수 있고 예약 API의 사용자 입력으로는
* 노출하지 않는 명령입니다. 저장된 예약 턴은 문자열 action을 유지하므로,
* 입력 경계와 실행 경계를 서로 다른 집합으로 관리합니다.
*/
export const INTERNAL_GENERAL_TURN_COMMAND_KEYS = [
'che_등용수락',
'che_방랑',
'che_NPC능동',
] as const satisfies readonly GeneralTurnCommandKey[];
export type InternalGeneralTurnCommandKey = (typeof INTERNAL_GENERAL_TURN_COMMAND_KEYS)[number];
export type SelectableGeneralTurnCommandKey = Exclude<GeneralTurnCommandKey, InternalGeneralTurnCommandKey>;
export type GeneralTurnCommandSpec = TurnCommandSpecBase<GeneralTurnCommandKey>;
export type GeneralTurnCommandModule = TurnCommandModule<GeneralTurnCommandSpec>;
@@ -127,6 +142,20 @@ const defaultImporters: Record<GeneralTurnCommandKey, GeneralTurnCommandImporter
export const isGeneralTurnCommandKey = (value: string): value is GeneralTurnCommandKey =>
GENERAL_TURN_COMMAND_KEYS.includes(value as GeneralTurnCommandKey);
const internalGeneralTurnCommandKeySet: ReadonlySet<GeneralTurnCommandKey> = new Set(
INTERNAL_GENERAL_TURN_COMMAND_KEYS
);
export const isInternalGeneralTurnCommandKey = (value: string): value is InternalGeneralTurnCommandKey =>
isGeneralTurnCommandKey(value) && internalGeneralTurnCommandKeySet.has(value);
export const isSelectableGeneralTurnCommandKey = (value: string): value is SelectableGeneralTurnCommandKey =>
isGeneralTurnCommandKey(value) && !internalGeneralTurnCommandKeySet.has(value);
export const SELECTABLE_GENERAL_TURN_COMMAND_KEYS = GENERAL_TURN_COMMAND_KEYS.filter(
(key): key is SelectableGeneralTurnCommandKey => !internalGeneralTurnCommandKeySet.has(key)
);
export class GeneralTurnCommandLoader {
private readonly cache = new Map<GeneralTurnCommandKey, Promise<GeneralTurnCommandModule>>();