feat: add stage exceptions

This commit is contained in:
Justin Lin committed 2025-04-21 11:19:59 +08:00
1 parent f7780c3d98
commit fb823814e0
11 files changed
+123 -43

No files matched your search

+7
View File
@@ -1,4 +1,5 @@
/* eslint-disable no-await-in-loop */
import { Condition } from './condition/Condition'
import {
IQuest,
IStage,
@@ -35,6 +36,12 @@ export class Quest {
return stage.id
}
}
for (const exception of stages.flatMap((stage) => stage.exceptions)) {
const condition = new Condition(exception.condition)
if (await condition.match(command)) {
return exception.id
}
}
return null
}
+4 -1
View File
@@ -1,17 +1,20 @@
import { IStage, ICommand, IFileExistenceChecker } from './schema'
import { Condition } from './condition/Condition'
import { StageException } from './schema/exception'
export class Stage {
id: string
name: string
private condition: Condition
private requirements: string[]
public readonly exceptions: StageException[]
constructor({ id, name, condition, requirements }: IStage) {
constructor({ id, name, condition, requirements, exceptions }: IStage) {
this.id = id
this.name = name || ''
this.condition = new Condition(condition)
this.requirements = requirements || []
this.exceptions = exceptions || []
}
async satisfies(
+4 -4
View File
@@ -1,9 +1,9 @@
import {
ICommand,
IFileExistenceChecker,
FileExistenceInput,
} from '../types.js'
import { ICondition } from '../schema/condition.js'
IFileInput,
ICondition,
} from '../schema'
import { PwdMatcher } from './PwdMatcher.js'
import { CommandMatcher } from './CommandMatcher.js'
import { ErrorMatcher } from './ErrorMatcher.js'
@@ -14,7 +14,7 @@ import { NotMatcher } from './NotMatcher.js'
import { checkFiles } from './FileMatcher.js'
export class Condition {
private files: FileExistenceInput[] = []
private files: IFileInput[] = []
private matchers: Matcher[] = []
constructor({ command, output, error, pwd, or, not, files }: ICondition) {
+4
View File
@@ -31,3 +31,7 @@ export const conditionSchema: z.ZodType<ICondition> =
or: z.lazy(() => z.array(conditionSchema).optional()),
not: z.lazy(() => conditionSchema.optional()),
})
export interface IFileExistenceChecker {
exists(file: IFileInput): Promise<boolean>
}
+23
View File
@@ -0,0 +1,23 @@
import { z } from 'zod'
import { conditionSchema } from './condition.js'
import { responseSchema } from './response.js'
export const exceptionSchema = z.object({
id: z.string(),
condition: conditionSchema,
response: responseSchema,
})
export type Exception = z.infer<typeof exceptionSchema>
export const stageExceptionSchema = exceptionSchema.extend({
catchAll: z.boolean().default(false),
})
export type StageException = z.infer<typeof stageExceptionSchema>
export const globalExceptionSchema = exceptionSchema.extend({
requirements: z.array(z.string()),
})
export type GlobalException = z.infer<typeof globalExceptionSchema>
+1 -19
View File
@@ -1,4 +1,4 @@
export { conditionSchema, ICondition } from './condition.js'
export * from './condition.js'
export { stageSchema, IStage } from './stage.js'
export { requirementsSchema, IRequirements } from './requirements.js'
export { responseSchema, IResponse } from './response.js'
@@ -11,24 +11,6 @@ export interface ICommand {
pwd?: string
}
export enum FileType {
FILE = 'file',
FOLDER = 'folder',
}
export interface FileInput {
path: string
type: FileType
}
export interface FileExistenceInput extends FileInput {
exists: boolean
}
export interface IFileExistenceChecker {
exists(file: FileInput): Promise<boolean>
}
export interface ISession {
completedStages: string[]
}
+2
View File
@@ -1,6 +1,7 @@
import { z } from 'zod'
import { conditionSchema } from './condition.js'
import { responseSchema } from './response.js'
import { stageExceptionSchema } from './exception.js'
export const stageSchema = z.object({
id: z.string().regex(/^[a-zA-Z0-9_-]+$/),
@@ -8,6 +9,7 @@ export const stageSchema = z.object({
requirements: z.array(z.string()),
condition: conditionSchema,
response: responseSchema,
exceptions: stageExceptionSchema.array().optional(),
})
export type IStage = z.infer<typeof stageSchema>