mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 03:20:12 +08:00
wip: replace packages with pure files
This commit is contained in:
1 parent
2d95ca382f
commit
87b8ca5d04
112 files changed
+740
-522
No files matched your search
@@ -0,0 +1,13 @@
|
||||
import { ICommand } from '../schema'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class CommandMatcher implements Matcher {
|
||||
private matcher: RegExp
|
||||
constructor(command: string, flags?: string) {
|
||||
this.matcher = new RegExp(command, flags)
|
||||
}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return !!command.command && this.matcher.test(command.command)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
ICommand,
|
||||
IFileExistenceChecker,
|
||||
ICondition,
|
||||
IFileExistenceInput,
|
||||
} from '../schema'
|
||||
import { PwdMatcher } from './PwdMatcher.js'
|
||||
import { CommandMatcher } from './CommandMatcher.js'
|
||||
import { ErrorMatcher } from './ErrorMatcher.js'
|
||||
import { Matcher } from './Matcher.js'
|
||||
import { OutputMatcher } from './OutputMatcher.js'
|
||||
import { OrMatcher } from './OrMatcher.js'
|
||||
import { NotMatcher } from './NotMatcher.js'
|
||||
import { checkFiles } from './FileMatcher.js'
|
||||
|
||||
export class Condition {
|
||||
private files: IFileExistenceInput[] = []
|
||||
private matchers: Matcher[] = []
|
||||
|
||||
constructor({ command, output, error, pwd, or, not, files }: ICondition) {
|
||||
if (command) this.matchers.push(new CommandMatcher(command))
|
||||
if (output) this.matchers.push(new OutputMatcher(output))
|
||||
if (pwd) this.matchers.push(new PwdMatcher(pwd))
|
||||
if (or) {
|
||||
const conditions = or.map((condition) => new Condition(condition))
|
||||
this.matchers.push(new OrMatcher(conditions))
|
||||
}
|
||||
if (not) this.matchers.push(new NotMatcher(new Condition(not)))
|
||||
if (files) this.files = files
|
||||
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
|
||||
}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return this.matchers.every((matcher) => {
|
||||
return matcher.match(command)
|
||||
})
|
||||
}
|
||||
|
||||
async check(checker: IFileExistenceChecker): Promise<boolean> {
|
||||
if (this.matchers.length === 0) return true
|
||||
return checkFiles(checker, this.files)
|
||||
}
|
||||
|
||||
async satisfies(
|
||||
command: ICommand,
|
||||
checker: IFileExistenceChecker
|
||||
): Promise<boolean> {
|
||||
// Error matcher is always true
|
||||
if (this.matchers.length === 1 && this.files.length === 0) return false
|
||||
// eslint-disable-next-line no-return-await
|
||||
return this.match(command) && (await this.check(checker))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Matcher } from './Matcher.js'
|
||||
import { ICommand } from '../schema'
|
||||
|
||||
export class ErrorMatcher implements Matcher {
|
||||
private matcher?: RegExp
|
||||
constructor(errorPattern?: string) {
|
||||
if (errorPattern) {
|
||||
this.matcher = new RegExp(errorPattern)
|
||||
}
|
||||
}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
if (!this.matcher) {
|
||||
return !command.error
|
||||
}
|
||||
return this.matcher.test(command.error || '')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { IFileExistenceInput, IFileExistenceChecker } from '../schema'
|
||||
|
||||
export async function checkFiles(
|
||||
checker: IFileExistenceChecker,
|
||||
files: IFileExistenceInput[]
|
||||
) {
|
||||
const existences = await Promise.all(
|
||||
files.map((file) => checker.exists(file))
|
||||
)
|
||||
return existences.every((exists, index) => exists === files[index].exists)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { ICommand } from '../schema'
|
||||
|
||||
export interface Matcher {
|
||||
match(command: ICommand): boolean
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ICommand } from '../schema'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class NotMatcher implements Matcher {
|
||||
constructor(private condition: Matcher) {}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return !this.condition.match(command)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ICommand } from '../schema'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class OrMatcher implements Matcher {
|
||||
constructor(private conditions: Matcher[]) {}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return this.conditions.some((condition) => condition.match(command))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ICommand } from '../schema'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class OutputMatcher implements Matcher {
|
||||
private matcher: RegExp
|
||||
constructor(pattern: string, args?: string) {
|
||||
this.matcher = new RegExp(pattern, args)
|
||||
}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return !!command.output && this.matcher.test(command.output.trim())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ICommand } from '../schema'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class PwdMatcher implements Matcher {
|
||||
constructor(private pwd: string) {}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return command.pwd === this.pwd
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user