mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
Merge branch 'game' into refactor-trpc
This commit is contained in:
commit
57d8f24930
23 files changed
+616
-13
No files matched your search
@@ -72,6 +72,14 @@ module.exports = {
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'no-useless-constructor': 'off',
|
||||
'@typescript-eslint/no-useless-constructor': 'error',
|
||||
'no-empty-function': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'error',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': 'error',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@linux-odyssey/game",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.ts",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ISession } from './types'
|
||||
|
||||
export class Session implements ISession {
|
||||
private completed: string[] = []
|
||||
|
||||
constructor({ completedStages }: ISession) {
|
||||
this.completed = completedStages
|
||||
}
|
||||
|
||||
get completedStages() {
|
||||
return this.completed
|
||||
}
|
||||
|
||||
complete(stageId: string) {
|
||||
this.completed.push(stageId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IStage, ICommand, IFileExistenceChecker, ISession } from './types'
|
||||
import { Condition } from './condition/Condition'
|
||||
|
||||
export class Stage {
|
||||
id: string
|
||||
name: string
|
||||
private condition: Condition
|
||||
private requirements: string[]
|
||||
|
||||
constructor({ id, name, condition, requirements }: IStage) {
|
||||
this.id = id
|
||||
this.name = name || ''
|
||||
this.condition = new Condition(condition)
|
||||
this.requirements = requirements || []
|
||||
}
|
||||
|
||||
async satisfies(
|
||||
command: ICommand,
|
||||
checker: IFileExistenceChecker
|
||||
): Promise<boolean> {
|
||||
return this.condition.match(command) && this.condition.check(checker)
|
||||
}
|
||||
|
||||
private checkRequirements(session: ISession): boolean {
|
||||
return this.requirements.every((req) =>
|
||||
session.completedStages.includes(req)
|
||||
)
|
||||
}
|
||||
|
||||
private finished(session: ISession): boolean {
|
||||
return session.completedStages.includes(this.id)
|
||||
}
|
||||
|
||||
active(session: ISession): boolean {
|
||||
return !this.finished(session) && this.checkRequirements(session)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ICommand } from '../types.js'
|
||||
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,43 @@
|
||||
import {
|
||||
ICommand,
|
||||
ICondition,
|
||||
IFileExistenceChecker,
|
||||
FileExistenceInput,
|
||||
} from '../types.js'
|
||||
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: FileExistenceInput[] = []
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Matcher } from './Matcher.js'
|
||||
import { ICommand } from '../types.js'
|
||||
|
||||
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 { FileExistenceInput, IFileExistenceChecker } from '../types'
|
||||
|
||||
export async function checkFiles(
|
||||
checker: IFileExistenceChecker,
|
||||
files: FileExistenceInput[]
|
||||
) {
|
||||
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 '../types.js'
|
||||
|
||||
export interface Matcher {
|
||||
match(command: ICommand): boolean
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ICommand } from '../types.js'
|
||||
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 '../types.js'
|
||||
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 '../types.js'
|
||||
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 '../types.js'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class PwdMatcher implements Matcher {
|
||||
constructor(private pwd: string) {}
|
||||
|
||||
match(command: ICommand): boolean {
|
||||
return command.pwd === this.pwd
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
@@ -0,0 +1,54 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const requirementsSchema = z.object({
|
||||
requirements: z.array(z.string()),
|
||||
})
|
||||
|
||||
export type IRequirements = z.infer<typeof requirementsSchema>
|
||||
|
||||
export const fileInputSchema = z.object({
|
||||
path: z.string(),
|
||||
type: z.enum(['file', 'folder']),
|
||||
})
|
||||
|
||||
export type IFileInput = z.infer<typeof fileInputSchema>
|
||||
|
||||
export const fileExistenceInputSchema = fileInputSchema.extend({
|
||||
exists: z.boolean(),
|
||||
})
|
||||
|
||||
export type IFileExistenceInput = z.infer<typeof fileExistenceInputSchema>
|
||||
|
||||
const baseConditionSchema = z.object({
|
||||
command: z.string().optional(),
|
||||
output: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
pwd: z.string().optional(),
|
||||
files: z.array(fileExistenceInputSchema).optional(),
|
||||
})
|
||||
|
||||
export type ICondition = z.infer<typeof baseConditionSchema> & {
|
||||
or?: ICondition[]
|
||||
not?: ICondition
|
||||
}
|
||||
|
||||
export const conditionSchema: z.ZodType<ICondition> =
|
||||
baseConditionSchema.extend({
|
||||
or: z.lazy(() => z.array(conditionSchema)).optional(),
|
||||
not: z.lazy(() => conditionSchema).optional(),
|
||||
})
|
||||
|
||||
export const responseSchema = z.object({
|
||||
type: z.enum(['narrative', 'dialogue']),
|
||||
content: z.string(),
|
||||
})
|
||||
|
||||
export const stageSchema = z.object({
|
||||
id: z.string().regex(/^[a-zA-Z0-9_-]+$/),
|
||||
name: z.string().optional(),
|
||||
requirements: z.array(z.string()),
|
||||
condition: conditionSchema,
|
||||
response: responseSchema,
|
||||
})
|
||||
|
||||
export type IStage = z.infer<typeof stageSchema>
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,45 @@
|
||||
export interface ICommand {
|
||||
command?: string
|
||||
output?: string
|
||||
error?: string
|
||||
pwd?: string
|
||||
}
|
||||
|
||||
export interface ICondition {
|
||||
command?: string
|
||||
output?: string
|
||||
error?: string
|
||||
pwd?: string
|
||||
or?: ICondition[]
|
||||
not?: ICondition
|
||||
files?: FileExistenceInput[]
|
||||
}
|
||||
|
||||
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 IStage {
|
||||
id: string
|
||||
name?: string
|
||||
requirements?: string[]
|
||||
condition: ICondition
|
||||
}
|
||||
|
||||
export interface ISession {
|
||||
completedStages: string[]
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import { test, expect } from '@jest/globals'
|
||||
import { IFileExistenceChecker, FileType, FileInput } from '../src/types.js'
|
||||
import { checkFiles } from '../src/condition/FileMatcher.js'
|
||||
import { Condition } from '../src/condition/Condition.js'
|
||||
|
||||
export class MockFileChecker implements IFileExistenceChecker {
|
||||
private files: FileInput[] = [
|
||||
{
|
||||
path: '/home/user/hello.txt',
|
||||
type: FileType.FILE,
|
||||
},
|
||||
{
|
||||
path: '/home/user/world.txt',
|
||||
type: FileType.FILE,
|
||||
},
|
||||
{
|
||||
path: '/home/user/Downloads',
|
||||
type: FileType.FOLDER,
|
||||
},
|
||||
]
|
||||
|
||||
async exists(file: FileInput): Promise<boolean> {
|
||||
return this.files.some((f) => f.path === file.path && f.type === file.type)
|
||||
}
|
||||
}
|
||||
|
||||
test('file matcher', async () => {
|
||||
const checker = new MockFileChecker()
|
||||
expect(
|
||||
await checkFiles(checker, [
|
||||
{
|
||||
path: '/home/user/hello.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
])
|
||||
).toBe(true)
|
||||
expect(
|
||||
await checkFiles(checker, [
|
||||
{
|
||||
path: '/home/user/not-exists.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
])
|
||||
).toBe(false)
|
||||
expect(
|
||||
await checkFiles(checker, [
|
||||
{
|
||||
path: '/home/user/not-exists.txt',
|
||||
type: FileType.FILE,
|
||||
exists: false,
|
||||
},
|
||||
])
|
||||
).toBe(true)
|
||||
expect(
|
||||
await checkFiles(checker, [
|
||||
{
|
||||
path: '/home/user/Downloads',
|
||||
type: FileType.FOLDER,
|
||||
exists: true,
|
||||
},
|
||||
])
|
||||
).toBe(true)
|
||||
expect(
|
||||
await checkFiles(checker, [
|
||||
{
|
||||
path: '/home/user/hello.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
{
|
||||
path: '/home/user/Downloads',
|
||||
type: FileType.FOLDER,
|
||||
exists: true,
|
||||
},
|
||||
])
|
||||
).toBe(true)
|
||||
expect(
|
||||
await checkFiles(checker, [
|
||||
{
|
||||
path: '/home/user/hello.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
{
|
||||
path: '/home/user/not-exist.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
])
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
test('condition with file matcher', async () => {
|
||||
const checker = new MockFileChecker()
|
||||
const condition = new Condition({
|
||||
files: [
|
||||
{
|
||||
path: '/home/user/hello.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(await condition.check(checker)).toBe(true)
|
||||
})
|
||||
@@ -0,0 +1,94 @@
|
||||
import { test, expect } from '@jest/globals'
|
||||
import { Condition } from '../src/condition/Condition'
|
||||
import { OutputMatcher } from '../src/condition/OutputMatcher'
|
||||
import { PwdMatcher } from '../src/condition/PwdMatcher'
|
||||
import { CommandMatcher } from '../src/condition/CommandMatcher'
|
||||
import { ErrorMatcher } from '../src/condition/ErrorMatcher.js'
|
||||
import { conditionSchema } from '../src/schema'
|
||||
|
||||
test('command match', () => {
|
||||
const matcher = new CommandMatcher('^echo start$')
|
||||
expect(matcher.match({ command: 'echo start' })).toBe(true)
|
||||
expect(matcher.match({ command: 'echo start1' })).toBe(false)
|
||||
// Currently not supported
|
||||
expect(matcher.match({ command: 'echo "start"' })).toBe(false)
|
||||
})
|
||||
|
||||
test('error matcher', () => {
|
||||
const matcher = new ErrorMatcher()
|
||||
expect(matcher.match({ error: '' })).toBe(true)
|
||||
expect(matcher.match({ error: 'permission denied' })).toBe(false)
|
||||
})
|
||||
|
||||
test('error matcher with specific error', () => {
|
||||
const matcher = new ErrorMatcher('permission denied')
|
||||
expect(matcher.match({ error: '' })).toBe(false)
|
||||
expect(matcher.match({ error: 'file not found' })).toBe(false)
|
||||
expect(matcher.match({ error: 'cannot open files: permission denied' })).toBe(
|
||||
true
|
||||
)
|
||||
})
|
||||
|
||||
test('pwd matcher', () => {
|
||||
const matcher = new PwdMatcher('/home/user')
|
||||
expect(matcher.match({ pwd: '/home/user' })).toBe(true)
|
||||
expect(matcher.match({ pwd: '/home/user1' })).toBe(false)
|
||||
expect(matcher.match({ pwd: '/home/user/anotherpath' })).toBe(false)
|
||||
expect(matcher.match({ pwd: '/var/home/user' })).toBe(false)
|
||||
})
|
||||
|
||||
test('output matcher', () => {
|
||||
const matcher = new OutputMatcher('^start$')
|
||||
expect(matcher.match({ output: 'start' })).toBe(true)
|
||||
expect(matcher.match({ output: 'start1' })).toBe(false)
|
||||
expect(matcher.match({ output: 'start\n' })).toBe(true)
|
||||
})
|
||||
|
||||
test('condition match command', () => {
|
||||
const condition = new Condition({
|
||||
command: '^echo start$',
|
||||
})
|
||||
|
||||
expect(
|
||||
condition.match({
|
||||
command: 'echo start',
|
||||
})
|
||||
).toBe(true)
|
||||
expect(
|
||||
condition.match({
|
||||
command: 'echo hello',
|
||||
})
|
||||
).toBe(false)
|
||||
expect(
|
||||
condition.match({ command: 'echo start', error: 'permission denied' })
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
test('condition with OR', () => {
|
||||
const condition = new Condition({
|
||||
or: [{ command: '^echo start$' }, { command: '^echo hello$' }],
|
||||
})
|
||||
expect(condition.match({ command: 'echo start' })).toBe(true)
|
||||
expect(condition.match({ command: 'echo hello' })).toBe(true)
|
||||
expect(condition.match({ command: 'echo start1' })).toBe(false)
|
||||
})
|
||||
|
||||
test('condition with NOT', () => {
|
||||
const condition = new Condition({
|
||||
not: { command: '^echo start$' },
|
||||
})
|
||||
|
||||
expect(condition.match({ command: 'echo start' })).toBe(false)
|
||||
expect(condition.match({ command: 'echo hello' })).toBe(true)
|
||||
})
|
||||
|
||||
it('should parse condition', () => {
|
||||
const condition = {
|
||||
command: 'echo start',
|
||||
output: 'start',
|
||||
not: {
|
||||
pwd: '/home/user',
|
||||
},
|
||||
}
|
||||
expect(conditionSchema.safeParse(condition).error).toBeUndefined()
|
||||
})
|
||||
@@ -0,0 +1,88 @@
|
||||
import { test, expect } from '@jest/globals'
|
||||
import { Stage } from '../src/Stage'
|
||||
import { FileType } from '../src/types'
|
||||
import { MockFileChecker } from './asyncCondition.test'
|
||||
import { Session } from '../src/Session'
|
||||
|
||||
const checker = new MockFileChecker()
|
||||
|
||||
test('check stage condition', async () => {
|
||||
const stage = new Stage({
|
||||
id: 'stage1',
|
||||
name: 'List the files using `ls`',
|
||||
condition: {
|
||||
command: 'ls',
|
||||
pwd: '/home/user',
|
||||
},
|
||||
})
|
||||
expect(
|
||||
await stage.satisfies(
|
||||
{
|
||||
command: 'ls',
|
||||
pwd: '/home/user',
|
||||
},
|
||||
checker
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
await stage.satisfies(
|
||||
{
|
||||
command: 'ls',
|
||||
pwd: '/home/user/Downloads',
|
||||
},
|
||||
checker
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
test('check stage with async condition truthy', async () => {
|
||||
const stage = new Stage({
|
||||
id: 'stage1',
|
||||
name: 'Create file',
|
||||
condition: {
|
||||
files: [
|
||||
{
|
||||
path: '/home/user/hello.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
expect(await stage.satisfies({}, checker)).toBe(true)
|
||||
})
|
||||
|
||||
test('check stage with async condition falsy', async () => {
|
||||
const stage = new Stage({
|
||||
id: 'stage1',
|
||||
name: 'Create file',
|
||||
condition: {
|
||||
files: [
|
||||
{
|
||||
path: '/home/user/not-exists.txt',
|
||||
type: FileType.FILE,
|
||||
exists: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
expect(await stage.satisfies({}, checker)).toBe(false)
|
||||
})
|
||||
|
||||
test('stage active checks', () => {
|
||||
const session = new Session({
|
||||
completedStages: ['stage1'],
|
||||
})
|
||||
const stage3 = new Stage({
|
||||
id: 'stage3',
|
||||
requirements: ['stage1', 'stage2'],
|
||||
condition: {},
|
||||
})
|
||||
expect(stage3.active(session)).toBe(false)
|
||||
|
||||
session.complete('stage2')
|
||||
expect(stage3.active(session)).toBe(true)
|
||||
|
||||
session.complete('stage3')
|
||||
expect(stage3.active(session)).toBe(false)
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.24.0":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b"
|
||||
integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.2.0"
|
||||
@@ -178,12 +178,12 @@
|
||||
|
||||
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a"
|
||||
integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==
|
||||
|
||||
"@babel/helper-remap-async-to-generator@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0"
|
||||
integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||
@@ -192,7 +192,7 @@
|
||||
|
||||
"@babel/helper-replace-supers@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793"
|
||||
integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==
|
||||
dependencies:
|
||||
"@babel/helper-environment-visitor" "^7.22.20"
|
||||
@@ -246,7 +246,7 @@
|
||||
|
||||
"@babel/helpers@^7.24.0":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b"
|
||||
integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==
|
||||
dependencies:
|
||||
"@babel/template" "^7.24.0"
|
||||
@@ -264,19 +264,19 @@
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac"
|
||||
integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3":
|
||||
version "7.23.3"
|
||||
resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a"
|
||||
integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.22.5"
|
||||
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3":
|
||||
version "7.23.3"
|
||||
resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d"
|
||||
integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.22.5"
|
||||
@@ -285,7 +285,7 @@
|
||||
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7":
|
||||
version "7.23.7"
|
||||
resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b"
|
||||
integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==
|
||||
dependencies:
|
||||
"@babel/helper-environment-visitor" "^7.22.20"
|
||||
@@ -293,7 +293,7 @@
|
||||
|
||||
"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2":
|
||||
version "7.21.0-placeholder-for-preset-env.2"
|
||||
resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
|
||||
integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
|
||||
|
||||
"@babel/plugin-syntax-async-generators@^7.8.4":
|
||||
@@ -987,7 +987,7 @@
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
|
||||
integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.23.4"
|
||||
@@ -3573,7 +3573,7 @@ cookie@0.6.0:
|
||||
|
||||
core-js-compat@^3.31.0, core-js-compat@^3.34.0:
|
||||
version "3.36.0"
|
||||
resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz"
|
||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190"
|
||||
integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==
|
||||
dependencies:
|
||||
browserslist "^4.22.3"
|
||||
@@ -9788,7 +9788,7 @@ yocto-queue@^0.1.0:
|
||||
|
||||
zod@^3.23.8:
|
||||
version "3.23.8"
|
||||
resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
|
||||
zod@^3.24.2:
|
||||
|
||||
Reference in new issue
Block a user