From 1d843f7355837bf61de359227329b02f5f238bbc Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Mon, 21 Apr 2025 21:42:54 +0800 Subject: [PATCH] refactor: remove unused quest-related schemas and consolidate exports --- packages/constants/src/index.ts | 1 - .../constants/src/quest/command-responder.ts | 11 ---------- packages/constants/src/quest/condition.ts | 21 ------------------ packages/constants/src/quest/exception.ts | 22 ------------------- .../constants/src/quest/file-condition.ts | 9 -------- packages/constants/src/quest/hint.ts | 5 ----- packages/constants/src/quest/index.ts | 11 ---------- .../src/quest/quest-detail-response.ts | 10 --------- packages/constants/src/quest/quest.ts | 16 -------------- packages/constants/src/quest/requirement.ts | 5 ----- packages/constants/src/quest/response.ts | 9 -------- packages/constants/src/quest/stage.ts | 18 --------------- packages/game/package.json | 5 ++++- packages/game/src/condition/CommandMatcher.ts | 2 +- packages/game/src/condition/Condition.ts | 4 ++-- packages/game/src/condition/ErrorMatcher.ts | 2 +- packages/game/src/condition/FileMatcher.ts | 4 ++-- packages/game/src/condition/Matcher.ts | 2 +- packages/game/src/condition/NotMatcher.ts | 2 +- packages/game/src/condition/OrMatcher.ts | 2 +- packages/game/src/condition/OutputMatcher.ts | 2 +- packages/game/src/condition/PwdMatcher.ts | 2 +- packages/game/src/index.ts | 6 +++++ packages/game/src/schema/index.ts | 10 ++++----- packages/game/src/schema/response.ts | 1 + packages/game/src/types.ts | 0 packages/game/tsconfig.json | 3 ++- server/package.json | 1 + server/src/models/quest.ts | 10 ++++----- 29 files changed, 35 insertions(+), 161 deletions(-) delete mode 100644 packages/constants/src/quest/command-responder.ts delete mode 100644 packages/constants/src/quest/condition.ts delete mode 100644 packages/constants/src/quest/exception.ts delete mode 100644 packages/constants/src/quest/file-condition.ts delete mode 100644 packages/constants/src/quest/hint.ts delete mode 100644 packages/constants/src/quest/index.ts delete mode 100644 packages/constants/src/quest/quest-detail-response.ts delete mode 100644 packages/constants/src/quest/quest.ts delete mode 100644 packages/constants/src/quest/requirement.ts delete mode 100644 packages/constants/src/quest/response.ts delete mode 100644 packages/constants/src/quest/stage.ts create mode 100644 packages/game/src/index.ts delete mode 100644 packages/game/src/types.ts diff --git a/packages/constants/src/index.ts b/packages/constants/src/index.ts index 8d1f50e..c6628e4 100644 --- a/packages/constants/src/index.ts +++ b/packages/constants/src/index.ts @@ -1,6 +1,5 @@ import { z } from 'zod' -export * from './quest/index.js' export * from './session.js' export const passwordPolicy = { diff --git a/packages/constants/src/quest/command-responder.ts b/packages/constants/src/quest/command-responder.ts deleted file mode 100644 index bbba51a..0000000 --- a/packages/constants/src/quest/command-responder.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { z } from 'zod' -import { conditionSchema } from './condition.js' -import { responseSchema } from './response.js' - -export const commandResponderSchema = z.object({ - condition: conditionSchema.optional(), - responses: z.array(responseSchema), - hints: z.array(z.string()), -}) - -export type CommandResponder = z.infer diff --git a/packages/constants/src/quest/condition.ts b/packages/constants/src/quest/condition.ts deleted file mode 100644 index e9f4519..0000000 --- a/packages/constants/src/quest/condition.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { z } from 'zod' -import { fileConditionSchema } from './file-condition.js' -import { toArray } from '../utils.js' - -const conditionSchemaBase = z.object({ - command: z.preprocess(toArray, z.array(z.string()).optional()), - output: z.preprocess(toArray, z.array(z.string()).optional()), - error: z.preprocess(toArray, z.array(z.string()).optional()), - pwd: z.preprocess(toArray, z.array(z.string()).optional()), - files: z.array(fileConditionSchema).optional(), -}) - -export type Condition = z.infer & { - not?: Condition - or?: Condition[] -} - -export const conditionSchema = conditionSchemaBase.extend({ - not: z.lazy(() => conditionSchema).optional(), - or: z.lazy(() => z.array(conditionSchema)).optional(), -}) as z.ZodType diff --git a/packages/constants/src/quest/exception.ts b/packages/constants/src/quest/exception.ts deleted file mode 100644 index 4014c6f..0000000 --- a/packages/constants/src/quest/exception.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { z } from 'zod' -import { conditionSchema } from './condition.js' -import { responseSchema } from './response.js' - -export const exceptionSchema = z.object({ - condition: conditionSchema, - responses: z.array(responseSchema), -}) - -export type Exception = z.infer - -export const stageExceptionSchema = exceptionSchema.extend({ - catchAll: z.boolean().default(false), -}) - -export type StageException = z.infer - -export const globalExceptionSchema = exceptionSchema.extend({ - requirements: z.array(z.string()), -}) - -export type GlobalException = z.infer diff --git a/packages/constants/src/quest/file-condition.ts b/packages/constants/src/quest/file-condition.ts deleted file mode 100644 index e86fe24..0000000 --- a/packages/constants/src/quest/file-condition.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { z } from 'zod' - -export const fileConditionSchema = z.object({ - path: z.string(), - type: z.string().optional(), - exists: z.boolean().default(true), -}) - -export type FileCondition = z.infer diff --git a/packages/constants/src/quest/hint.ts b/packages/constants/src/quest/hint.ts deleted file mode 100644 index 49f3852..0000000 --- a/packages/constants/src/quest/hint.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { z } from 'zod' - -export const hintSchema = z.array(z.string()) - -export type Hint = z.infer diff --git a/packages/constants/src/quest/index.ts b/packages/constants/src/quest/index.ts deleted file mode 100644 index 6ab676a..0000000 --- a/packages/constants/src/quest/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export * from './requirement.js' -export * from './hint.js' -export * from './file-condition.js' -export * from './condition.js' -export * from './response.js' -export * from './command-responder.js' -export * from './stage-exception.js' -export * from './stage.js' -export * from './exception.js' -export * from './quest.js' -export * from './quest-detail-response.js' diff --git a/packages/constants/src/quest/quest-detail-response.ts b/packages/constants/src/quest/quest-detail-response.ts deleted file mode 100644 index 44ceabd..0000000 --- a/packages/constants/src/quest/quest-detail-response.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from 'zod' - -export const questDetailResponseSchema = z.object({ - id: z.string(), - title: z.string(), - instruction: z.string(), - requirements: z.array(z.string()), -}) - -export type QuestDetailResponse = z.infer diff --git a/packages/constants/src/quest/quest.ts b/packages/constants/src/quest/quest.ts deleted file mode 100644 index 5a5c899..0000000 --- a/packages/constants/src/quest/quest.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { z } from 'zod' -import { stageSchema } from './stage.js' -import { globalExceptionSchema } from './exception.js' -import { requirementSchema } from './requirement.js' - -export const questSchema = z.object({ - id: z.string(), - title: z.string(), - image: z.string(), - instruction: z.string(), - requirements: requirementSchema, - stages: z.array(stageSchema), - exceptions: z.array(globalExceptionSchema).default([]), -}) - -export type Quest = z.infer diff --git a/packages/constants/src/quest/requirement.ts b/packages/constants/src/quest/requirement.ts deleted file mode 100644 index f702582..0000000 --- a/packages/constants/src/quest/requirement.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { z } from 'zod' - -export const requirementSchema = z.array(z.string()).default([]) - -export type Requirement = z.infer diff --git a/packages/constants/src/quest/response.ts b/packages/constants/src/quest/response.ts deleted file mode 100644 index f02ebeb..0000000 --- a/packages/constants/src/quest/response.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { z } from 'zod' -import { toArray } from '../utils.js' - -export const responseSchema = z.object({ - type: z.enum(['narrative', 'dialogue']).default('narrative'), - content: z.preprocess(toArray, z.array(z.string())), -}) - -export type Response = z.infer diff --git a/packages/constants/src/quest/stage.ts b/packages/constants/src/quest/stage.ts deleted file mode 100644 index 643ce2e..0000000 --- a/packages/constants/src/quest/stage.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { z } from 'zod' -import { stageExceptionSchema } from './exception.js' -import { conditionSchema } from './condition.js' -import { responseSchema } from './response.js' -import { hintSchema } from './hint.js' -import { requirementSchema } from './requirement.js' - -export const stageSchema = z.object({ - id: z.string(), - task: z.string(), - exceptions: stageExceptionSchema.array().default([]), - requirements: requirementSchema, - condition: conditionSchema, - responses: z.array(responseSchema), - hints: hintSchema.default([]), -}) - -export type Stage = z.infer diff --git a/packages/game/package.json b/packages/game/package.json index 5854459..b6b6072 100644 --- a/packages/game/package.json +++ b/packages/game/package.json @@ -1,7 +1,10 @@ { "name": "@linux-odyssey/game", "version": "1.0.0", - "main": "dist/index.ts", + "main": "dist/index.js", + "exports": { + ".": "./dist/index.js" + }, "license": "MIT", "scripts": { "build": "tsc -b" diff --git a/packages/game/src/condition/CommandMatcher.ts b/packages/game/src/condition/CommandMatcher.ts index 3f71bcd..ccafed1 100644 --- a/packages/game/src/condition/CommandMatcher.ts +++ b/packages/game/src/condition/CommandMatcher.ts @@ -1,4 +1,4 @@ -import { ICommand } from '../types.js' +import { ICommand } from '../schema' import { Matcher } from './Matcher.js' export class CommandMatcher implements Matcher { diff --git a/packages/game/src/condition/Condition.ts b/packages/game/src/condition/Condition.ts index 15927fa..179f4a1 100644 --- a/packages/game/src/condition/Condition.ts +++ b/packages/game/src/condition/Condition.ts @@ -1,8 +1,8 @@ import { ICommand, IFileExistenceChecker, - IFileInput, ICondition, + IFileExistenceInput, } from '../schema' import { PwdMatcher } from './PwdMatcher.js' import { CommandMatcher } from './CommandMatcher.js' @@ -14,7 +14,7 @@ import { NotMatcher } from './NotMatcher.js' import { checkFiles } from './FileMatcher.js' export class Condition { - private files: IFileInput[] = [] + private files: IFileExistenceInput[] = [] private matchers: Matcher[] = [] constructor({ command, output, error, pwd, or, not, files }: ICondition) { diff --git a/packages/game/src/condition/ErrorMatcher.ts b/packages/game/src/condition/ErrorMatcher.ts index 6fd1d15..99c1704 100644 --- a/packages/game/src/condition/ErrorMatcher.ts +++ b/packages/game/src/condition/ErrorMatcher.ts @@ -1,5 +1,5 @@ import { Matcher } from './Matcher.js' -import { ICommand } from '../types.js' +import { ICommand } from '../schema' export class ErrorMatcher implements Matcher { private matcher?: RegExp diff --git a/packages/game/src/condition/FileMatcher.ts b/packages/game/src/condition/FileMatcher.ts index c364e09..7d1771b 100644 --- a/packages/game/src/condition/FileMatcher.ts +++ b/packages/game/src/condition/FileMatcher.ts @@ -1,8 +1,8 @@ -import { FileExistenceInput, IFileExistenceChecker } from '../types' +import { IFileExistenceInput, IFileExistenceChecker } from '../schema' export async function checkFiles( checker: IFileExistenceChecker, - files: FileExistenceInput[] + files: IFileExistenceInput[] ) { const existences = await Promise.all( files.map((file) => checker.exists(file)) diff --git a/packages/game/src/condition/Matcher.ts b/packages/game/src/condition/Matcher.ts index 0af7c33..0585d7c 100644 --- a/packages/game/src/condition/Matcher.ts +++ b/packages/game/src/condition/Matcher.ts @@ -1,4 +1,4 @@ -import { ICommand } from '../types.js' +import { ICommand } from '../schema' export interface Matcher { match(command: ICommand): boolean diff --git a/packages/game/src/condition/NotMatcher.ts b/packages/game/src/condition/NotMatcher.ts index 1e9a846..b4e42c5 100644 --- a/packages/game/src/condition/NotMatcher.ts +++ b/packages/game/src/condition/NotMatcher.ts @@ -1,4 +1,4 @@ -import { ICommand } from '../types.js' +import { ICommand } from '../schema' import { Matcher } from './Matcher.js' export class NotMatcher implements Matcher { diff --git a/packages/game/src/condition/OrMatcher.ts b/packages/game/src/condition/OrMatcher.ts index 70c2091..06e6e21 100644 --- a/packages/game/src/condition/OrMatcher.ts +++ b/packages/game/src/condition/OrMatcher.ts @@ -1,4 +1,4 @@ -import { ICommand } from '../types.js' +import { ICommand } from '../schema' import { Matcher } from './Matcher.js' export class OrMatcher implements Matcher { diff --git a/packages/game/src/condition/OutputMatcher.ts b/packages/game/src/condition/OutputMatcher.ts index 89aa9a2..e633f01 100644 --- a/packages/game/src/condition/OutputMatcher.ts +++ b/packages/game/src/condition/OutputMatcher.ts @@ -1,4 +1,4 @@ -import { ICommand } from '../types.js' +import { ICommand } from '../schema' import { Matcher } from './Matcher.js' export class OutputMatcher implements Matcher { diff --git a/packages/game/src/condition/PwdMatcher.ts b/packages/game/src/condition/PwdMatcher.ts index 781a7c5..7e0d4f7 100644 --- a/packages/game/src/condition/PwdMatcher.ts +++ b/packages/game/src/condition/PwdMatcher.ts @@ -1,4 +1,4 @@ -import { ICommand } from '../types.js' +import { ICommand } from '../schema' import { Matcher } from './Matcher.js' export class PwdMatcher implements Matcher { diff --git a/packages/game/src/index.ts b/packages/game/src/index.ts new file mode 100644 index 0000000..368b63b --- /dev/null +++ b/packages/game/src/index.ts @@ -0,0 +1,6 @@ +export * from './schema' +export * from './Quest' +export * from './Session' +export * from './Event' +export * from './Stage' +export * from './Exception' diff --git a/packages/game/src/schema/index.ts b/packages/game/src/schema/index.ts index 282f071..962afb8 100644 --- a/packages/game/src/schema/index.ts +++ b/packages/game/src/schema/index.ts @@ -1,9 +1,9 @@ export * from './condition.js' -export { stageSchema, IStage } from './stage.js' -export { requirementsSchema, IRequirements } from './requirements.js' -export { responseSchema, IResponse } from './response.js' -export { questSchema, IQuest } from './quest.js' -export { exceptionSchema, IException } from './exception.js' +export * from './stage.js' +export * from './requirements.js' +export * from './response.js' +export * from './quest.js' +export * from './exception.js' export interface ICommand { command?: string diff --git a/packages/game/src/schema/response.ts b/packages/game/src/schema/response.ts index c085d77..9e4077d 100644 --- a/packages/game/src/schema/response.ts +++ b/packages/game/src/schema/response.ts @@ -3,6 +3,7 @@ import { z } from 'zod' export const responseSchema = z.object({ type: z.enum(['narrative', 'dialogue']), content: z.string(), + hint: z.string().optional(), }) export type IResponse = z.infer diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts deleted file mode 100644 index e69de29..0000000 diff --git a/packages/game/tsconfig.json b/packages/game/tsconfig.json index 49e05ce..e0965f1 100644 --- a/packages/game/tsconfig.json +++ b/packages/game/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", - "rootDir": "./src" + "rootDir": "./src", + "composite": true }, "include": ["src"] } diff --git a/server/package.json b/server/package.json index 00dc766..f34b346 100644 --- a/server/package.json +++ b/server/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@linux-odyssey/constants": "*", + "@linux-odyssey/game": "*", "@linux-odyssey/file-graph": "*", "@linux-odyssey/models": "*", "@linux-odyssey/utils": "*", diff --git a/server/src/models/quest.ts b/server/src/models/quest.ts index 80ea69a..218ff05 100644 --- a/server/src/models/quest.ts +++ b/server/src/models/quest.ts @@ -3,7 +3,7 @@ import fs from 'fs/promises' import path from 'path' import yaml from 'yaml' -import { Quest, questSchema } from '@linux-odyssey/constants' +import { questSchema, globalExceptionSchema, IQuest } from '@linux-odyssey/game' import logger from '../utils/logger.js' class QuestValidationError extends Error { @@ -19,7 +19,7 @@ class QuestValidationError extends Error { } class QuestManager { - private quests = new Map() + private quests = new Map() private questDirectory = path.join(process.cwd(), '..', 'quests') get(id: string) { @@ -51,11 +51,11 @@ class QuestManager { private async loadGlobalExceptions() { const exceptionsPath = path.join(this.questDirectory, 'exceptions.yml') const body = await fs.readFile(exceptionsPath, 'utf-8') - return yaml.parse(body) + return globalExceptionSchema.array().parse(yaml.parse(body)) } async loadAndUpdateQuests() { - const { exceptions } = await this.loadGlobalExceptions() + const exceptions = await this.loadGlobalExceptions() return this.mapQuests(async (id, questPath) => { const files = await fs.readdir(questPath) if (!files.includes('game.yml')) { @@ -78,7 +78,7 @@ class QuestManager { image, ...questData, }) - quest.exceptions.push(...exceptions) + quest.exceptions = [...exceptions] this.quests.set(id, quest) } catch (error) { logger.error(`Error parsing quest ${id}`, { error })