diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..88808c5 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,5 @@ +{ + "extension": ["test.js"], + "spec": "out/**/*.test.js", + "watch-files": ["out/**/*.test.js"] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index aecda74..0c07599 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,7 @@ "version": "2.0.0", "tasks": [ { - "label": "tsc watch", + "label": "build", "type": "npm", "script": "compile:watch", "isBackground": true, @@ -10,6 +10,9 @@ "kind": "build", "isDefault": true }, + "runOptions": { + "runOn": "folderOpen" + }, "presentation": { "reveal": "never", "echo": false, diff --git a/content/core/actions/FetchSticksAction.ts b/content/core/actions/FetchSticksAction.ts new file mode 100644 index 0000000..e7801e9 --- /dev/null +++ b/content/core/actions/FetchSticksAction.ts @@ -0,0 +1,9 @@ +import { registerAction } from '@actions'; +import { Game } from '@game'; + +registerAction('Fetch Sticks', (qty) => { + Game.current.board.addTask({ + taskId: "core:fetch-sticks", + options: {} + }) +}); \ No newline at end of file diff --git a/content/core/actions/GatherRocksAction.ts b/content/core/actions/GatherRocksAction.ts new file mode 100644 index 0000000..c0f0ba5 --- /dev/null +++ b/content/core/actions/GatherRocksAction.ts @@ -0,0 +1,9 @@ +import { registerAction } from '@actions'; +import { Game } from '@game'; + +registerAction('Gather Rocks', (qty) => { + Game.current.board.addTask({ + taskId: 'core:gather-rocks', + options: {} + }) +}); diff --git a/content/core/items/Items.ts b/content/core/items/Items.ts new file mode 100644 index 0000000..6bb224f --- /dev/null +++ b/content/core/items/Items.ts @@ -0,0 +1,18 @@ +import { Item } from '@items'; + +export const LOG = new Item() + .setName("Log") + .setId('core:resources/log'); + +export const ROCK = new Item() + .setName("Rock") + .setId('core:resources/rock'); + +export const STICK = new Item() + .setName("Stick") + .setId('core:resources/stick'); + + +// slate, flint X normal, flake +// limestone: large, small +// shale \ No newline at end of file diff --git a/content/core/tasks/ChopTreeTask.ts b/content/core/tasks/ChopTreeTask.ts new file mode 100644 index 0000000..8e97a5c --- /dev/null +++ b/content/core/tasks/ChopTreeTask.ts @@ -0,0 +1,25 @@ +import chalk from 'chalk'; +import { Game } from '@game'; +import { registerTask, Task } from '@tasks'; +import { LOG } from '../items/Items.js'; + +// TODO cleanup imports, use aliases + +class ChopTreeTask extends Task { + work = 100; + + reward() { + Game.current.inv.add(LOG, 1); + } + + get title() { + return chalk.yellow('Chop Trees'); + } + + get status() { + return chalk.yellow('LOGGING'); + } +} + + +registerTask('core:chop-trees', ChopTreeTask); \ No newline at end of file diff --git a/content/core/tasks/FetchSticksTask.ts b/content/core/tasks/FetchSticksTask.ts new file mode 100644 index 0000000..5440356 --- /dev/null +++ b/content/core/tasks/FetchSticksTask.ts @@ -0,0 +1,21 @@ +import { Task, registerTask } from "@tasks"; +import chalk from 'chalk'; +import { Game } from '@game'; +import { LOG, STICK } from '../items/Items.js'; + +class FetchSticksTask extends Task { + work = 100; + reward(): void { + Game.current.inv.add(STICK, 1); + } + + get title() { + return chalk.yellow('Chop Trees'); + } + + get status() { + return chalk.yellow('LOGGING'); + } +} + +registerTask('core:fetch-sticks', FetchSticksTask); \ No newline at end of file diff --git a/content/core/tasks/GatherRocksTask.ts b/content/core/tasks/GatherRocksTask.ts new file mode 100644 index 0000000..02d3160 --- /dev/null +++ b/content/core/tasks/GatherRocksTask.ts @@ -0,0 +1,22 @@ +import { Task, registerTask } from "@tasks"; +import chalk from 'chalk'; +import { Game } from '@game'; +import { ROCK } from '../items/Items.js'; + +class GatherRocksTask extends Task { + work = 100; + + reward(): void { + Game.current.inv.add(ROCK, 1); + } + + get title() { + return chalk.yellow('Chop Trees'); + } + + get status() { + return chalk.yellow('LOGGING'); + } +} + +registerTask('core:gather-rocks', GatherRocksTask); \ No newline at end of file diff --git a/content/core/themes/standard.ts b/content/core/themes/standard.ts index 16fd29b..16524ad 100644 --- a/content/core/themes/standard.ts +++ b/content/core/themes/standard.ts @@ -1,4 +1,4 @@ -import { registerTheme } from '@theme'; +import { registerTheme } from '@themes'; import chalk from 'chalk' registerTheme("default", {}); diff --git a/lib/aliases.mjs b/lib/aliases.mjs index baca07c..1c7f461 100644 --- a/lib/aliases.mjs +++ b/lib/aliases.mjs @@ -1,7 +1,11 @@ import path from 'path'; const moduleAliases = { - "@theme": "./out/src/ui/Theme.js" + "@themes": "./out/src/registries/Themes.js", + "@actions": "./out/src/registries/Actions.js", + "@tasks": "./out/src/registries/Tasks.js", + "@items": "./out/src/registries/Items.js", + "@game": "./out/src/Game.js" }; const getAliases = () => { diff --git a/package.json b/package.json index 5409b79..71dd1a9 100644 --- a/package.json +++ b/package.json @@ -7,16 +7,19 @@ "dependencies": { "@types/blessed": "^0.1.17", "@types/bonjour": "^3.5.8", + "@types/chai": "^4.2.19", "@types/faker": "^5.5.6", + "@types/mocha": "^8.2.2", "@types/uuid": "^8.3.0", "bonjour": "^3.5.0", + "chai": "^4.3.4", "chalk": "^4.1.1", "deepmerge": "^4.2.2", "faker": "^5.5.3", "frigid": "^1.3.8", "fs-extra": "^10.0.0", "get-port": "^5.1.1", - "logger": "^0.0.1", + "mocha": "^9.0.1", "module-alias": "^2.2.2", "neo-blessed": "^0.2.0", "printable-characters": "^1.0.42", @@ -29,8 +32,10 @@ }, "scripts": { "compile:watch": "tsc --watch", - "start": "node --loader ./lib/aliases.mjs --enable-source-maps out/src/index.js", + "start": "node --no-warnings --loader ./lib/aliases.mjs --enable-source-maps out/src/index.js", "dev": "supervisor -w out -n exit -t -k --exec yarn -- start", - "prod": "git fetch && git pull && yarn && tsc && yarn start" + "prod": "git fetch && git pull && yarn && tsc && yarn start", + "test": "mocha", + "lint": "eslint src/**/*.ts" } } diff --git a/src/Game.ts b/src/Game.ts index 64cf726..25c4472 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -5,78 +5,77 @@ import { TaskList } from './TaskList.js'; import { Inventory } from './Inventory.js'; import { Menu } from './ui/Menu.js'; import Time, { Tickable } from './Time.js'; -import { render, Renderable, setTitle } from './ui/UI.js'; -import log from './log.js'; -import { ChopTreeTask } from './tasks/ChopTreeTask.js'; -import { Task } from './tasks/Task.js'; +import { render, Renderable, setTitle, start } from './ui/UI.js'; import { ready } from './multiplayer/mDNS.js'; import faker from 'faker'; let game = null; export class Game extends Frigid implements Tickable, Renderable { - pawns: Pawn[] = []; - selected: Pawn; - inventory: Inventory; - board: TaskList; - menu: Menu; - clock: Time; - name: string; + pawns: Pawn[] = []; + selected: Pawn; + inventory: Inventory; + board: TaskList; + menu: Menu; + clock: Time; + name: string; - [DEBUG] = true; + [DEBUG] = true; - static get current(): Game { - if (!game) throw new Error('Somehow called a game before it existed?'); - return game; - } + static get current(): Game { + if (!game) throw new Error('Somehow called a game before it existed?'); + return game; + } - async tick() { - for(const pawn of this.pawns) { - pawn.tick(); - } - render(); - } + async tick() { + for(const pawn of this.pawns) { + pawn.tick(); + } + render(); + } - get inv() { return this.inventory; } + get inv() { return this.inventory; } - removePawn(pawn: Pawn) { - if(pawn === this.selected) { - if(this.pawns.indexOf(this.selected) === this.pawns.length - 1) this.advanceSelection(-1); - else this.advanceSelection(1); - } + removePawn(pawn: Pawn) { + if(pawn === this.selected) { + if(this.pawns.indexOf(this.selected) === this.pawns.length - 1) this.advanceSelection(-1); + else this.advanceSelection(1); + } - this.pawns = this.pawns.filter(testPawn => { - return pawn !== testPawn; - }); - } + this.pawns = this.pawns.filter(testPawn => { + return pawn !== testPawn; + }); + } - advanceSelection(number) { - let index = this.pawns.indexOf(this.selected); - this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)]; - } - - ctor () { - game = this; - this.name ??= faker.address.city(); - setTitle(this.name); - this.pawns ??= []; - this.selected ??= this.pawns[0] || null; - this.menu = new Menu(); - this.board ??= new TaskList(); - this.inventory ??= new Inventory(); - this.clock ??= new Time(); - this.clock.thing = this; - this.clock.start(); - ready(this.name); - render(this); - } + advanceSelection(number) { + let index = this.pawns.indexOf(this.selected); + this.selected = this.pawns[Math.min(Math.max(index + number, 0), this.pawns.length - 1)]; + } + + ctor () { + game = this; + start(); + this.name ??= faker.address.city(); + setTitle(this.name); + this.pawns ??= []; + this.selected ??= this.pawns[0] || null; + this.menu = new Menu(); + this.board ??= new TaskList(); + this.inventory ??= new Inventory(); + this.inventory.validate(); + this.clock ??= new Time(); + this.clock.thing = this; + this.clock.start(); + ready(this.name); + render(this); + } - static serializationDependencies() { - return [Pawn, Inventory, TaskList, Time, ChopTreeTask, Task]; - } + static serializationDependencies() { + return [ Pawn, Inventory, TaskList, Time ]; + } - render() { - this.menu.render(); - this.board.render(); - } + render() { + this.menu.render(); + this.board.render(); + } } \ No newline at end of file diff --git a/src/Inventory.ts b/src/Inventory.ts index 0ee90c5..137ff65 100644 --- a/src/Inventory.ts +++ b/src/Inventory.ts @@ -1,37 +1,59 @@ import { Serializable } from 'frigid'; import { Game } from './Game.js'; -import { Item, ItemState } from './Item.js'; +import { Item, ItemState } from './registries/Items.js'; +import { Popup } from './ui/Popup.js'; import { Renderable } from './ui/UI.js'; export class Inventory extends Serializable implements Renderable { - items: ItemState[]; + items: ItemState[]; - ctor() { - this.items ??= []; - } + ctor() { + this.items ??= []; + } - static serializationDependencies() { - return [ItemState]; - } + validate() { + const invalid: ItemState[] = []; + for(const itemState of this.items) { + try { + itemState.item; + } catch { + invalid.push(itemState); + } + } + if(invalid.length === 0) return; + + for(const itemState of invalid) { + this.remove(itemState); + } + Popup.show('Invalid ItemStates removed:\n\n' + invalid.map(itemState => itemState.qty + 'x ' + itemState.itemId).join('\n')); + } - add(item: Item, qty: number = 1) { - const id = item.id; - const existingArr = this.items.filter(itemState => { - return itemState.itemId === id; - }); - let existing: ItemState = null; - if(existingArr.length === 1) { - existing = existingArr[0]; - } - if(existing) { - existing.qty += qty; - } else { - this.items.push(new ItemState(item, qty, {})); - } - Game.current.sync(); - } + static serializationDependencies() { + return [ItemState]; + } - render() { - return this.items.map(item => item.render()).join('\n'); - } + remove(itemState: ItemState) { + this.items = this.items.filter(test => test !== itemState); + } + + add(item: Item, qty: number = 1) { + const id = item.id; + const existingArr = this.items.filter(itemState => { + return itemState.itemId === id; + }); + let existing: ItemState = null; + if(existingArr.length === 1) { + existing = existingArr[0]; + } + if(existing) { + existing.qty += qty; + } else { + this.items.push(new ItemState(item, qty, {})); + } + Game.current.sync(); + } + + render() { + return this.items.map(item => item.render()).join('\n'); + } } diff --git a/src/Item.ts b/src/Item.ts deleted file mode 100644 index 58859d3..0000000 --- a/src/Item.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Serializable } from 'frigid'; -import { getTheme } from './ui/Theme.js'; -import { Renderable } from './ui/UI.js'; - -export type ItemID = string; - -const items = new Map(); - -// ITEMS SHALL BE SINGULAR -export class Item extends Serializable { - static LOG = new Item().setName("Log").setId('resources:log'); - - name = ''; - id: ItemID = ''; - - setName(name) { - this.name = name; - return this; - } - - setId(id: ItemID) { - this.id = id; - items.set(this.id, this); - return this; - } -} - -export class ItemState extends Serializable implements Renderable { - qty: number; - itemId: ItemID; - data: any; - - get item() { - return items.get(this.itemId); - } - - constructor(item: Item, amount: number, data: any) { - super(); - this.qty = amount; - this.itemId = item.id; - this.data = data; - } - - render() { - return getTheme().normal(` ${this.item.name}{|}${this.qty} `); - } -} \ No newline at end of file diff --git a/src/Pawn.ts b/src/Pawn.ts index 81317ab..338310b 100644 --- a/src/Pawn.ts +++ b/src/Pawn.ts @@ -1,13 +1,11 @@ import { Serializable } from 'frigid'; import faker from 'faker'; -import log from './log.js'; -import { Task } from './tasks/Task.js'; +import { Task } from './registries/Tasks.js'; import Time, { Tickable } from './Time.js'; -import { ChopTreeTask } from './tasks/ChopTreeTask.js'; import { Game } from './Game.js'; import { render } from './ui/UI.js'; import { Memory } from './Memory.js'; -import { getTheme } from './ui/Theme.js'; +import { getTheme } from './registries/Themes.js'; const LABORS = { CUT_TREE: Symbol('CUT_TREE'), @@ -81,7 +79,6 @@ export class Pawn extends Serializable implements Tickable { } ctor() { - log.info('Pawn::ctor') this.name ??= { first: faker.name.firstName(), last: faker.name.lastName() @@ -132,8 +129,8 @@ export class Pawn extends Serializable implements Tickable { } } - static serializationDependencies() { - return [Task, ChopTreeTask] + static serializationDependencies(): (typeof Serializable)[] { + return [Task] } toString() { diff --git a/src/Progressbar.ts b/src/Progressbar.ts index a715cfe..c386b5d 100644 --- a/src/Progressbar.ts +++ b/src/Progressbar.ts @@ -1,5 +1,5 @@ import chalk from "chalk"; -import { getTheme } from "./ui/Theme.js"; +import { getTheme } from "./registries/Themes.js"; export enum ProgressbarStyle { indicator = 'indicator', @@ -9,7 +9,7 @@ export enum ProgressbarStyle { export const barCache: Map = new Map(); export function progressbar(completion: number, width: number, style: ProgressbarStyle = ProgressbarStyle.indicator) { - const cacheKey = `${completion}-${width}-${style}`; + const cacheKey = `${Math.round(completion * width * 8)}-${width}-${style}`; if(barCache.has(cacheKey)) { stats.cacheHits ++; return barCache.get(cacheKey); diff --git a/src/Reflection.ts b/src/Reflection.ts new file mode 100644 index 0000000..2c8772e --- /dev/null +++ b/src/Reflection.ts @@ -0,0 +1 @@ +export type Class = new() => T; \ No newline at end of file diff --git a/test.js b/src/Task.ts similarity index 100% rename from test.js rename to src/Task.ts diff --git a/src/TaskList.ts b/src/TaskList.ts index 1717703..49ef4f0 100644 --- a/src/TaskList.ts +++ b/src/TaskList.ts @@ -1,8 +1,6 @@ import { Serializable } from 'frigid'; -import { ChopTreeTask } from "./tasks/ChopTreeTask.js"; -import { Game } from './Game.js'; -import { Task } from "./tasks/Task.js"; -import { render, Renderable, tasksPanel } from './ui/UI.js'; +import { Task, taskClasses } from './registries/Tasks.js'; +import { render, Renderable, panels } from './ui/UI.js'; export class TaskList extends Serializable implements Renderable { tasks: Task[] = []; @@ -14,10 +12,16 @@ export class TaskList extends Serializable implements Renderable { } static serializationDependencies() { - return [ChopTreeTask, Task]; + return Array.from(taskClasses.values()); } - addTask(task) { + addTask({taskId, options}: TaskOptions) { + if(!taskClasses.has(taskId)) + throw new Error('unknown task: ' + taskId); + + const taskClass = taskClasses.get(taskId); + const task = new taskClass(); + this.tasks = [...this.tasks, task]; } @@ -27,9 +31,19 @@ export class TaskList extends Serializable implements Renderable { render() { // const width = tasksPanel.width; - tasksPanel.setContent(`${this.tasks.map(task => { + panels.left.setContent(`${this.tasks.map(task => { return task.toString(); }).join('\n')}`); // return this.tasks.map(task => task.toString()).join('\n'); } } + +const taskTypes = {}; +export function registerTask(name, clazz) { + taskTypes[name] = clazz; +} + +export type TaskOptions = { + taskId: string, + options: any +} \ No newline at end of file diff --git a/src/Time.test.ts b/src/Time.test.ts new file mode 100644 index 0000000..338f8c9 --- /dev/null +++ b/src/Time.test.ts @@ -0,0 +1,31 @@ +// TODO pull in full test framework and coverage shit from vogue +import { expect } from 'chai'; +import Time from './Time.js'; + +describe('Time', () => { + describe('normalize timestamps correctly', () => { + it('0', () => { + const time = new Time(0); + expect(time.toString()).to.equal("0:00 Jan 1, 0001 CE"); + }) + it('-1', () => { + const time = new Time(-1); + expect(time.toString()).to.equal("23:59 Dec 31, 0001 BCE"); + }) + it('1', () => { + const time = new Time(1); + expect(time.toString()).to.equal("0:01 Jan 1, 0001 CE"); + expect(time) + }) + it('0.25', () => { + const time = new Time(0.25); + expect(time.toString()).to.equal("0:00 Jan 1, 0001 CE"); + expect(time.second).to.equal(15); + }) + it('-0.25', () => { + const time = new Time(-0.25); + expect(time.toString()).to.equal("23:59 Dec 31, 0001 BCE"); + expect(time.second).to.equal(45); + }) + }) +}); \ No newline at end of file diff --git a/src/Time.ts b/src/Time.ts index 25cf313..63b6534 100644 --- a/src/Time.ts +++ b/src/Time.ts @@ -1,11 +1,10 @@ import chalk from "chalk"; import { Serializable } from "frigid"; -import { getTheme } from "./ui/Theme.js"; +import { getTheme } from "./registries/Themes.js"; import { Renderable } from "./ui/UI.js"; type AbbreviatedMonthName = string; - const daysInMonth = [ 31, 28, 31, 30, 31, 30, @@ -63,21 +62,13 @@ export default class Time extends Serializable implements Renderable { return `${sym} ${ getTheme().normal(`${ - this.hour.toString().padStart(2, ' ') - }:${ - this.minute.toString().padStart(2, '0') - } ${ - months[this.month] - } ${ - this.day + 1 - }, ${ - this.normalizedYear + this.toString() }`) }`; } toString() { - return `${this.hour}:${this.minute.toString().padStart(2, '0')} ${months[this.month]} ${this.day + 1}, ${this.normalizedYear}` + return `${this.hour}:${Math.floor(this.minute).toString().padStart(2, '0')} ${months[this.month]} ${this.day + 1}, ${this.normalizedYear}` } ctor() { @@ -89,6 +80,10 @@ export default class Time extends Serializable implements Renderable { this.year ??= 0; } + get second() { + return Math.floor((this.minute % 1) * 60) + } + get stamp() { let minute = this.minute; let hour = this.hour; @@ -123,8 +118,8 @@ export default class Time extends Serializable implements Renderable { setTimeout(this.doTick.bind(this), 0); } - advanceTime(minutes) { - this.minute ++; + advanceTime(seconds) { + this.minute += seconds / 60; this.normalize() } @@ -136,7 +131,10 @@ export default class Time extends Serializable implements Renderable { } } + + normalize() { + // while(t) while(this.minute >= 60) { this.minute -= 60; this.hour ++; @@ -145,7 +143,6 @@ export default class Time extends Serializable implements Renderable { this.minute += 60; this.hour --; } - while(this.hour >= 24) { this.hour -= 24; this.day ++; diff --git a/src/index.ts b/src/index.ts index fe35d88..7fe35bd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,30 +1,36 @@ -import { Game } from './Game.js'; import { render } from './ui/UI.js'; import { ensureDirSync } from 'fs-extra'; import { lstatSync } from 'fs'; import { parse, resolve } from 'path'; import walkSync from 'walk-sync'; import { fileURLToPath } from 'url'; +import { Game } from '@game'; const saveFile = process.argv[2] || 'data/world01.json'; ensureDirSync(parse(saveFile).dir); + +// TODO extract extension loading into separate file +console.log('df-idle: Loading extensions'); const extensionsPath = resolve(parse(fileURLToPath(import.meta.url)).dir, '../content'); const extensions = walkSync(extensionsPath) - .map(path => resolve(extensionsPath, path)) - .filter(path => lstatSync(path).isFile()) - .filter(path => parse(path).ext === '.js') - .map(path => import(path)); + .map(path => resolve(extensionsPath, path)) + .filter(path => lstatSync(path).isFile()) + .filter(path => parse(path).ext === '.js'); + // .map(path => import(path)); -Promise.all(extensions).then((extensions) => { - - // TODO move render logic into game, so that the ui doesnt exist until the game does... - // maybe, i mean, an argument could be made for not that, because the game - // isnt necessarily the entire thing, its just one instance of a save file. - // But probably the initial menu screens will be their own thing entirely. - const game = Game.create(saveFile); - render(game); +console.log('found', extensions.length, 'extensions'); -}); \ No newline at end of file +for(const path of extensions) { + console.log('=== [', path, '] ==='); + await import(path); + console.log(); +} + +// TODO move render logic into game, so that the ui doesnt exist until the game does... +// maybe, i mean, an argument could be made for not that, because the game +// isnt necessarily the entire thing, its just one instance of a save file. +// But probably the initial menu screens will be their own thing entirely. +const game = Game.create(saveFile); \ No newline at end of file diff --git a/src/log.ts b/src/log.ts deleted file mode 100644 index 9641e7b..0000000 --- a/src/log.ts +++ /dev/null @@ -1,15 +0,0 @@ -import logger from 'logger'; - -const log: { - fatal: (...args) => void, - error: (...args) => void, - warn: (...args) => void, - info: (...args) => void, - debug: (...args) => void, -} = logger.createLogger('debug.log'); - -(log as any).format = function(level, date, message) { - return `${date.getTime()} [${level}]${message}`; -}; - -export default log; \ No newline at end of file diff --git a/src/multiplayer/Player.ts b/src/multiplayer/Player.ts index 641e8e1..c1e99fa 100644 --- a/src/multiplayer/Player.ts +++ b/src/multiplayer/Player.ts @@ -1,4 +1,4 @@ -import { ItemState } from '../Item.js'; +import { ItemState } from '../registries/Items.js'; import WebSocket from 'ws'; import { Pawn } from '../Pawn.js'; import { Game } from '../Game.js'; diff --git a/src/multiplayer/mDNS.ts b/src/multiplayer/mDNS.ts index b3352c2..26e9bad 100644 --- a/src/multiplayer/mDNS.ts +++ b/src/multiplayer/mDNS.ts @@ -1,11 +1,10 @@ import bonjour from 'bonjour'; -import log from '../log.js'; import getPort from 'get-port'; import os from 'os' import * as uuid from 'uuid'; import faker from 'faker'; import chalk from 'chalk'; -import { Item } from '../Item.js'; +import { Item } from '../registries/Items.js'; import WebSocket from 'ws'; import { Popup } from '../ui/Popup.js'; import { inspect } from 'util' @@ -71,7 +70,6 @@ mdns.find({ p.name = service.name; p.host = service.host; p.port = service.port; - log.info('Found player', p); devices.push(p); }).on("down", (service) => { // TODO remove player from MP diff --git a/src/registries/Actions.ts b/src/registries/Actions.ts new file mode 100644 index 0000000..7f69640 --- /dev/null +++ b/src/registries/Actions.ts @@ -0,0 +1,20 @@ +import { getTheme } from "@themes"; +import { Renderable } from "../ui/UI.js"; + +export const actions: Action[] = []; + +export function registerAction(name: string, invoke: (qty: number) => void) { + console.log('Registered action', name); + actions.push(new Action(name, invoke)) +} + +export class Action { + name: string; + qty: number; + invoke: (qty: number) => void; + + constructor(name: string, done: (qty: number) => void) { + this.name = name; + this.invoke = done; + } +} \ No newline at end of file diff --git a/src/registries/Items.ts b/src/registries/Items.ts new file mode 100644 index 0000000..471515d --- /dev/null +++ b/src/registries/Items.ts @@ -0,0 +1,57 @@ +import { Serializable } from 'frigid'; +import { getTheme } from './Themes.js'; +import { Renderable } from '../ui/UI.js'; + +export type ItemID = string; + +const items = new Map(); + +// ITEMS SHALL BE SINGULAR +export class Item extends Serializable { + + name = ''; + id: ItemID = ''; + + setName(name) { + this.name = name; + this.register(false); + return this; + } + + setId(id: ItemID) { + this.id = id; + this.register(false); + return this; + } + + register(force = true) { + if((!this.id || !this.name) && !force) return; + console.log('Added item', (this.name ?? "[No Name]").padStart(20, ' '), `| (${this.id})`) + items.set(this.id, this); + return this; + } +} + +export class ItemState extends Serializable implements Renderable { + qty: number; + itemId: ItemID; + data: any; + + get item() { + if(!items.has(this.itemId)) + throw new Error('unknown item: ' + this.itemId); + return items.get(this.itemId); + } + + constructor(item: Item, amount: number, data: any) { + super(); + this.qty = amount; + this.itemId = item.id; + this.data = data; + } + + render() { + return getTheme().normal(` ${this.item.name}{|}${this.qty} `); + } +} + diff --git a/src/registries/Tasks.ts b/src/registries/Tasks.ts new file mode 100644 index 0000000..cf0abd4 --- /dev/null +++ b/src/registries/Tasks.ts @@ -0,0 +1,75 @@ +import { Serializable } from 'frigid'; +import EventEmitter from 'events'; +import chalk from 'chalk'; +import { Pawn } from '../Pawn.js'; +import { Game } from '../Game.js'; +import { panels } from '../ui/UI.js'; +import { progressbar, ProgressbarStyle } from '../Progressbar.js'; +import { Class } from '../Reflection.js'; + +export const taskClasses: Map> = new Map(); + +export abstract class Task extends Serializable { + progress = 0; + worker: Pawn; + data: any; + + ctor() { + this.worker ??= null; + this.testCompletion(); + } + + abstract reward(): void; + abstract work: number; + + get completed() { + return this.completion >= 1; + } + + stopJob() { + this.worker = null; + } + + doWork(work = 1, pawn: Pawn) { + this.worker = pawn; + this.progress += work; + this.testCompletion(); + } + + testCompletion() { + if (this.progress >= this.work) { + this.reward(); + Game.current.board.removeTask(this); + } + } + + claim(pawn: Pawn) { + this.worker = pawn; + } + + get completion() { + return Math.min(1, this.progress / this.work); + } + + toString() { + // HACK magic number 2 here, is the border + // of the panel + const width = panels.left.width - 2; + const left = ' ' + this.title + ' ' + (this.worker?.toString() || chalk.bold.black('Queued')); + const bar = width - 2; + return `${left}\n ${progressbar(this.completion, bar, ProgressbarStyle.progress)}\n`; + } + + get title() { + return chalk.bgRedBright.black('[Abstract Task]'); + } + + get status() { + return chalk.bgRedBright.black('DOING A TASK'); + } +} + +export function registerTask(id: string, taskClass: Class) { + console.log('Registered task', id); + taskClasses.set(id, taskClass) +} \ No newline at end of file diff --git a/src/ui/Theme.ts b/src/registries/Themes.ts similarity index 97% rename from src/ui/Theme.ts rename to src/registries/Themes.ts index d1d8436..74b1a49 100644 --- a/src/ui/Theme.ts +++ b/src/registries/Themes.ts @@ -7,7 +7,6 @@ import chalk from 'chalk'; chalk.level = 2; import merge from 'deepmerge'; -import log from '../log.js'; type StyleFunction = (text: string) => string; @@ -79,7 +78,7 @@ let currentTheme = backupTheme; const themes: Map = new Map(); export function registerTheme(name: ThemeName, theme: Partial) { - log.info('registering theme', name) + console.log('Registered theme', name); themes.set(name, merge(backupTheme, theme)); } diff --git a/src/tasks/ChopTreeTask.ts b/src/tasks/ChopTreeTask.ts deleted file mode 100644 index 91f8c63..0000000 --- a/src/tasks/ChopTreeTask.ts +++ /dev/null @@ -1,31 +0,0 @@ -import chalk from 'chalk'; -import { Game } from '../Game.js'; -import { Item } from '../Item.js'; -import { Pawn } from '../Pawn.js'; -import { Task } from './Task.js'; - - -export class ChopTreeTask extends Task { - work = 100; - - constructor(count) { - super(); - - } - - reward() { - Game.current.inv.add(Item.LOG, 1); - } - - static serializationDependencies() { - return [Pawn]; - } - - get title() { - return chalk.yellow('Chop Trees'); - } - - get status() { - return chalk.yellow('LOGGING'); - } -} diff --git a/src/tasks/Task.ts b/src/tasks/Task.ts deleted file mode 100644 index 2c8b1c0..0000000 --- a/src/tasks/Task.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Serializable } from 'frigid'; -import EventEmitter from 'events'; -import chalk from 'chalk'; -import { Pawn } from '../Pawn.js'; -import { render, tasksPanel } from '../ui/UI.js'; -import { Game } from '../Game.js'; -import { progressbar, ProgressbarStyle } from '../Progressbar.js'; - -export class Task extends Serializable { - work = 0; - progress = 0; - worker: Pawn; - - ctor() { - this.worker ??= null; - this.testCompletion(); - } - - reward() {} - - get completed() { - return this.completion >= 1; - } - - stopJob() { - this.worker = null; - } - - doWork(work = 1, pawn: Pawn) { - this.worker = pawn; - this.progress += work; - this.testCompletion(); - } - - testCompletion() { - if (this.progress >= this.work) { - this.reward(); - Game.current.board.removeTask(this); - } - } - - claim(pawn: Pawn) { - this.worker = pawn; - } - - get completion() { - return Math.min(1, this.progress / this.work); - } - - toString() { - // HACK magic number 2 here, is the border - // of the panel - const width = tasksPanel.width - 2; - const left = ' ' + this.title + ' ' + (this.worker?.toString() || chalk.bold.black('Queued')); - const bar = width - 2; - return `${left}\n ${progressbar(this.completion, bar, ProgressbarStyle.progress)}\n`; - } - - get title() { - return chalk.bgRedBright.black('[Abstract Task]'); - } - - get status() { - return chalk.bgRedBright.black('DOING A TASK'); - } -} \ No newline at end of file diff --git a/src/ui/GiftPopup.ts b/src/ui/GiftPopup.ts index 4baeaf0..c5379e6 100644 --- a/src/ui/GiftPopup.ts +++ b/src/ui/GiftPopup.ts @@ -1,11 +1,11 @@ import chalk from 'chalk'; import blessed from 'neo-blessed'; import { Game } from '../Game.js'; -import { ItemState } from '../Item.js'; +import { ItemState } from '../registries/Items.js'; import { Player } from "../multiplayer/Player"; import { Pawn } from '../Pawn.js'; -import { getTheme } from './Theme.js'; -import { boxStyle, screen } from './UI.js'; +import { getTheme } from '../registries/Themes.js'; +import { boxStyle, panels } from './UI.js'; export class GiftPopup { box; @@ -30,7 +30,7 @@ export class GiftPopup { this.send(); } if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); - screen.remove(this.box); + panels.screen.remove(this.box); } else if (key.full === 'up') { this.selected --; } else if (key.full === 'down') { @@ -44,7 +44,7 @@ export class GiftPopup { }); this.render(); for(const pawn of Game.current.pawns) this.pawns.set(pawn, 0); - screen.append(this.box); + panels.screen.append(this.box); this.box.focus(); Game.current.clock.pause(); } @@ -80,6 +80,6 @@ export class GiftPopup { } return pawns.join('\n') })()}\n\n{|}${getTheme().hotkey('escape')}${getTheme().normal(': Cancel ')}\n{|}${getTheme().hotkey('enter')}${getTheme().normal(': Okay ')}`); - screen.render(); + panels.screen.render(); } } \ No newline at end of file diff --git a/src/ui/Menu.ts b/src/ui/Menu.ts index 5312b86..46667a4 100644 --- a/src/ui/Menu.ts +++ b/src/ui/Menu.ts @@ -1,111 +1,111 @@ import { Pawn } from '../Pawn.js'; -import log from '../log.js'; -import { menuPanel, Renderable } from './UI.js'; +import { panels, Renderable } from './UI.js'; import { Game } from '../Game.js'; import { progressbar, stats } from '../Progressbar.js'; import { Popup } from './Popup.js'; import mdns from '../multiplayer/mDNS.js'; -import { getTheme } from './Theme.js'; +import { getTheme } from '@themes'; import { inspect } from 'util'; import PawnsView from './view/PawnsView.js'; import InventoryView from './view/InventoryView.js'; import MultiplayerView from './view/MultiplayerView.js'; import { View } from './View.js'; +import { ActionsView } from './view/ActionsView.js'; const clamp = (min, max, value) => Math.min(Math.max(value, min), max); // TODO move KeypressAcceptor to ui something idk export interface KeypressAcceptor { - keypress(key: {full: string}): void + keypress(key: {full: string}): void } export class Menu implements Renderable { - trees: number = 10; - viewIndex: number = 0; - views: View[] = [ - new PawnsView(), - new InventoryView(), - new MultiplayerView() - ] + trees: number = 10; + viewIndex: number = 0; + views: View[] = [ + new PawnsView(), + new InventoryView(), + new MultiplayerView(), + new ActionsView() + ] - get view() { - return this.views[this.viewIndex]; - } + get view() { + return this.views[this.viewIndex]; + } - advanceView() { - this.viewIndex ++; - this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); - } + advanceView() { + this.viewIndex ++; + this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); + } - regressView() { - this.viewIndex --; - this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); - } + regressView() { + this.viewIndex --; + this.viewIndex = clamp(0, this.views.length - 1, this.viewIndex); + } - constructor() { - menuPanel.on('keypress', (evt, key) => { - log.info('keypress', key); - - if (key.full === 'left') { - this.regressView(); - } else if (key.full === 'right') { - this.advanceView(); - - // debugging hotkeys - } else if (key.full === '1') { - Popup.show(inspect(stats)); - } else if (key.full === 'z') { - Game.current.pawns.push(new Pawn()); - } else if (key.full === 'x') { - Game.current.board.clear(); - } else this.view.keypress(key); + constructor() { + panels.right.on('keypress', (evt, key) => { + + if (key.full === 'left') { + this.regressView(); + } else if (key.full === 'right') { + this.advanceView(); + + // debugging hotkeys + } else if (key.full === '1') { + Popup.show(inspect(stats)); + } else if (key.full === 'z') { + Game.current.pawns.push(new Pawn()); + } else if (key.full === 'x') { + Game.current.board.clear(); + } else this.view.keypress(key); - // if(this.view === View.MULTIPLAYER) { - // if (key.full === 'enter') { - // new GiftPopup(mdns.players[this.multiplayerSelected]); - // // mdns.players[this.multiplayerSelected].sendItem(null); - // } else if (key.full === 'up') { - // this.multiplayerSelected --; - // } else if (key.full === 'down') { - // this.multiplayerSelected ++; - // } - // } + // if(this.view === View.MULTIPLAYER) { + // if (key.full === 'enter') { + // new GiftPopup(mdns.players[this.multiplayerSelected]); + // // mdns.players[this.multiplayerSelected].sendItem(null); + // } else if (key.full === 'up') { + // this.multiplayerSelected --; + // } else if (key.full === 'down') { + // this.multiplayerSelected ++; + // } + // } - // TODO add colortest debug screen! + // TODO add colortest debug screen! - Game.current.sync(); - }); - } + Game.current.sync(); + }); + } - renderTopBar() { - const idlers = Game.current.pawns.filter(pawn => pawn.idle); - return ` ${Game.current.clock.render()}{|}${getTheme().normal(`Idle: ${idlers.length}`)} `; - } + renderTopBar() { + const idlers = Game.current.pawns.filter(pawn => pawn.idle); + return ` ${Game.current.clock.render()}{|}${getTheme().normal(`Idle: ${idlers.length}`)} `; + } - renderView() { - const colSpace = ((menuPanel.width - 2) / 2); - return `{center}${(() => { - return Object.values(this.views).map((view, idx) => { - if(idx === this.viewIndex) { - return getTheme().tab.selected(` ${view.name} `); - } else { - return getTheme().tab.normal(` ${view.name} `); - } - }).join(''); - })()}{/center}\n\n${ - this.view.render() - }`; - } + renderView() { + const colSpace = ((panels.right.width - 2) / 2); + return `{center}${(() => { + return Object.values(this.views).map((view, idx) => { + if(idx === this.viewIndex) { + return getTheme().tab.selected(` ${view.name} `); + } else { + return getTheme().tab.normal(` ${view.name} `); + } + }).join(''); + })()}{/center}\n\n${ + this.view.render() + }`; + } - render() { - const width = menuPanel.width - 2; - const hr = getTheme().normal('━'.repeat(width)); - const content = [ - this.renderTopBar(), - hr, - this.renderView(), - ].join('\n'); - menuPanel.setContent(content); - } + render() { + const width = panels.right.width - 2; + const hr = getTheme().normal('━'.repeat(width)); + const content = [ + this.renderTopBar(), + hr, + this.renderView(), + ].join('\n'); + panels.right.setContent(content); + } } \ No newline at end of file diff --git a/src/ui/PawnDetails.ts b/src/ui/PawnDetails.ts index 9f21e6a..69a63f3 100644 --- a/src/ui/PawnDetails.ts +++ b/src/ui/PawnDetails.ts @@ -4,7 +4,7 @@ import { Game } from '../Game.js'; import { stringify } from '../Memory.js'; import { Pawn } from '../Pawn.js'; import Time from '../Time.js'; -import { boxStyle, screen } from './UI.js'; +import { boxStyle, panels } from './UI.js'; export class PawnDetails { box; @@ -23,7 +23,7 @@ export class PawnDetails { this.box.on('keypress', (evt, key) => { if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); - screen.remove(this.box); + panels.screen.remove(this.box); } else if (key.full === 'up') { // this.selected --; } else if (key.full === 'down') { @@ -36,7 +36,7 @@ export class PawnDetails { this.render(); }); this.render(); - screen.append(this.box); + panels.screen.append(this.box); this.box.focus(); Game.current.clock.pause(); } @@ -55,6 +55,6 @@ export class PawnDetails { }: Cancel \n{|}${ chalk.green('enter') }: Okay `); - screen.render(); + panels.screen.render(); } } \ No newline at end of file diff --git a/src/ui/Popup.ts b/src/ui/Popup.ts index 8cdbfa5..bd152cb 100644 --- a/src/ui/Popup.ts +++ b/src/ui/Popup.ts @@ -1,8 +1,8 @@ import chalk from 'chalk'; import blessed from 'neo-blessed'; import { Game } from '../Game.js'; -import { getTheme } from './Theme.js'; -import { boxStyle, screen } from './UI.js'; +import { getTheme } from '@themes'; +import { boxStyle, panels } from './UI.js'; export class Popup { box; @@ -17,34 +17,34 @@ export class Popup { left: 'center', width: '100%', height: 'shrink', - // content: getTheme().normal(content) + `\n\n{|}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `), + content: getTheme().normal(content) + `\n\n{right}` + getTheme().hotkey('enter') + getTheme().normal(`: Okay `) + '{/right}', tags: true, ...boxStyle(), }); - let stuff = ' '; - for(let i = 16; i < 34; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 52; i < 70; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 88; i < 106; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 124; i < 142; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 160; i < 178; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 196; i < 214; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - stuff += '\n '; - for(let i = 34; i < 52; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 70; i < 88; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 106; i < 124; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; - stuff += '\n'; - for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) - this.box.setContent(stuff) + // let stuff = ' '; + // for(let i = 16; i < 34; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 52; i < 70; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 88; i < 106; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 124; i < 142; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 160; i < 178; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 196; i < 214; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // stuff += '\n '; + // for(let i = 34; i < 52; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 70; i < 88; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 106; i < 124; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 142; i < 160; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 178; i < 196; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // for(let i = 214; i < 232; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%6===0?chalk.reset(' '):''}`); stuff += '\n '; + // stuff += '\n'; + // for(let i = 232; i < 256; i ++) stuff += chalk.bgAnsi256(i).black(` ${i.toString().padStart(3, ' ')} ${(i-15)%18===0?'\n':''}`) + // this.box.setContent(stuff) this.box.on('keypress', (evt, key) => { if(key.full === 'escape' || key.full === 'enter') { Game.current.clock.start(); - screen.remove(this.box); + panels.screen.remove(this.box); } }); - screen.append(this.box); + panels.screen.append(this.box); this.box.focus(); Game.current.clock.pause(); } diff --git a/src/ui/UI.ts b/src/ui/UI.ts index dc1f67b..cf5d122 100644 --- a/src/ui/UI.ts +++ b/src/ui/UI.ts @@ -1,12 +1,7 @@ import blessed from 'neo-blessed'; import ansi from 'sisteransi'; -import { getTheme } from './Theme.js'; - -export const screen = blessed.screen({ - smartCSR: true, - terminal: 'xterm-256color' -}); +import { getTheme } from '../registries/Themes.js'; export interface Renderable { render(): void @@ -31,64 +26,108 @@ export const boxStyle = () => { }; }; -let currentRenderable = null; +let leftPanel: any; +let rightPanel: any; +let titleBar: any; +let screen: any; +let currentRenderable: Renderable = null; +let started = false; + +function assertStarted() { + if(!started) throw new Error('Attempted accessing UI before starting it!'); +} + +function assertNotStarted() { + if(started) throw new Error('Attempted starting UI when already started!'); +} + +export function isStarted() { + return started; +} + +export const panels = { + get left() { + assertStarted() + return leftPanel; + }, + get right() { + assertStarted() + return rightPanel; + }, + get screen() { + assertStarted() + return screen; + } +} + +export function setTitle(title: string) { + assertStarted(); + titleBar.setContent(` ${getTheme().header(title)}{|}${getTheme().subheader('v0.1.0')} {/}`); +} + export function render(thing?: Renderable) { - if(!!thing) currentRenderable = thing; - currentRenderable.render(); - screen.render(); + assertStarted(); + if(!!thing) currentRenderable = thing; + + currentRenderable.render(); + screen.render(); } -export const tasksPanel = blessed.box({ - top: 1, - left: 0, - width: '50%+1', - height: '100%-1', - ...boxStyle(), - tags: true -}); +export function start() { + assertNotStarted(); + screen = blessed.screen({ + smartCSR: true, + terminal: 'xterm-256color' + }); -export const menuPanel = blessed.box({ - top: 1, - left: '50%+1', - width: '50%', - height: '100%-1', - ...boxStyle(), - tags: true -}); + leftPanel = blessed.box({ + top: 1, + left: 0, + width: '50%', + height: '100%-1', + ...boxStyle(), + tags: true + }); -const titleBar = blessed.box({ - top: 0, - left: 0, - width: '100%', - height: 1, - tags: true, -}); + rightPanel = blessed.box({ + top: 1, + right: 0, + width: '50%', + height: '100%-1', + ...boxStyle(), + tags: true + }); -export function setTitle(title) { - titleBar.setContent(` ${getTheme().header(title)}{|}${getTheme().subheader('v0.1.0')} {/}`); -} + titleBar = blessed.box({ + top: 0, + left: 0, + width: '100%', + height: 1, + tags: true, + }); -setTitle(''); + screen.append(leftPanel); + screen.append(rightPanel); + screen.append(titleBar); + rightPanel.focus(); -menuPanel.focus(); + process.stdout.write(ansi.cursor.hide); -screen.append(tasksPanel); -screen.append(menuPanel); -screen.append(titleBar); + screen.key(['C-c'], function(ch, key) { + process.stdout.write(ansi.cursor.show); + setTimeout(_ => { + process.exit(0); + }) + }); -process.stdout.write(ansi.cursor.hide); + screen.key('f2', () => { + rightPanel.focus(); + }); -screen.key(['C-c'], function(ch, key) { - process.stdout.write(ansi.cursor.show); - setTimeout(_ => { - process.exit(0); - }) -}); + screen.key('f1', () => { + leftPanel.focus(); + }); -tasksPanel.key('f2', () => { - menuPanel.focus(); -}); - -menuPanel.key('f1', () => { - tasksPanel.focus(); -}); \ No newline at end of file + started = true; + setTitle(''); +} \ No newline at end of file diff --git a/src/ui/view/ActionsView.ts b/src/ui/view/ActionsView.ts new file mode 100644 index 0000000..896657b --- /dev/null +++ b/src/ui/view/ActionsView.ts @@ -0,0 +1,33 @@ +import { getTheme } from "../../registries/Themes.js"; +import { Game } from "../../Game.js"; +import { Renderable } from "../UI.js"; +import { View } from "../View.js"; +import { actions } from "@actions"; + +export class ActionsView extends View { + actionIdx: number = 0; + + constructor() { + super(); + this.name = 'Actions'; + } + + keypress(key) { + if(key.full === 'up') { + this.actionIdx --; + } else if (key.full === 'down') { + this.actionIdx ++; + } else if (key.full === 'enter') { + actions[this.actionIdx].invoke(1); + } + } + render() { + return actions.map((action, idx) => `${(() => { + if(this.actionIdx === idx) { + return getTheme().selected(' ❯ ' + action.name); + } else { + return getTheme().normal(' ' + action.name); + } + })()}`).join('\n'); + } +} \ No newline at end of file diff --git a/src/ui/view/MultiplayerView.ts b/src/ui/view/MultiplayerView.ts index 7d770a5..2bce850 100644 --- a/src/ui/view/MultiplayerView.ts +++ b/src/ui/view/MultiplayerView.ts @@ -1,7 +1,7 @@ import { GiftPopup } from "../GiftPopup.js"; import { View } from "../View.js" import mdns from '../../multiplayer/mDNS.js'; -import { getTheme } from "@theme"; +import { getTheme } from "@themes"; export default class MultiplayerView extends View { diff --git a/src/ui/view/PawnsView.ts b/src/ui/view/PawnsView.ts index 118010b..c9b7c9b 100644 --- a/src/ui/view/PawnsView.ts +++ b/src/ui/view/PawnsView.ts @@ -1,8 +1,8 @@ -import { getTheme } from "@theme"; +import { getTheme } from "@themes"; import { Game } from "../../Game.js"; import { progressbar } from "../../Progressbar.js"; import { PawnDetails } from "../PawnDetails.js"; -import { menuPanel } from "../UI.js"; +import { panels } from "../UI.js"; import { View } from "../View.js"; export default class PawnsView extends View { @@ -30,7 +30,7 @@ export default class PawnsView extends View { let str = ''; if(selected) { str += ` ${getTheme().selected(` ❯ ${pawn.toString()}`)}{|}${pawn.status} \n`; - str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (menuPanel.width - 4) / 2)} \n`; + str += ` ${getTheme().normal('Energy')}{|}${progressbar(pawn.energy / 100, (panels.right.width - 4) / 2)} \n`; } else { str += ` ${getTheme().normal(pawn.toString())}{|}${pawn.status} `; } diff --git a/tsconfig.json b/tsconfig.json index 49ad934..4977fa7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,18 @@ { "compilerOptions": { "target": "ES2020", - "module": "ES2020", + "module": "ESNext", "moduleResolution": "Node", "allowSyntheticDefaultImports": true, "outDir": "out", "declaration": true, "sourceMap": true, "paths": { - "@theme": ["./src/ui/Theme"] + "@themes": ["./src/registries/Themes"], + "@actions": ["./src/registries/Actions"], + "@tasks": ["./src/registries/Tasks"], + "@items": ["./src/registries/Items"], + "@game": ["./src/Game"] } }, "include": [ diff --git a/yarn.lock b/yarn.lock index 92e3e54..4a1b4c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,6 +14,11 @@ dependencies: "@types/node" "*" +"@types/chai@^4.2.19": + version "4.2.19" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.19.tgz#80f286b515897413c7a35bdda069cc80f2344233" + integrity sha512-jRJgpRBuY+7izT7/WNXP/LsMO9YonsstuL+xuvycDyESpoDoIAsMd7suwpB4h9oEWB+ZlPTqJJ8EHomzNhwTPQ== + "@types/faker@^5.5.6": version "5.5.6" resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.6.tgz#039b700a9d8ad9150ecc842bf5e717e2027b6f75" @@ -23,6 +28,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== +"@types/mocha@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0" + integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw== + "@types/node@*": version "15.12.2" resolved "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz" @@ -31,21 +41,64 @@ version "8.3.0" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" -ansi-styles@^4.1.0: +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" dependencies: color-convert "^2.0.1" +anymatch@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" @@ -65,6 +118,18 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" @@ -76,13 +141,59 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -chalk@^4.1.1: +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +chai@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^4.1.0, chalk@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz" dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +chokidar@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" @@ -98,6 +209,25 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +debug@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -120,6 +250,11 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -137,19 +272,54 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + ensure-posix-path@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + faker@^5.5.3: version "5.5.3" resolved "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + frigid@^1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.8.tgz#a16919821e5426344bc98d301099f7631d2bae8a" - integrity sha512-i3HgB/5hQsALyumWoRlBvEpAXfTmM3Xw+Ica6E9mTASUVYtqZQ8mzUX8/3zscTUM4bCKhSa7MSvXl9L7pt5ICg== + version "1.3.9" + resolved "https://registry.yarnpkg.com/frigid/-/frigid-1.3.9.tgz#f9353b3d0ea5e38f69a2bb7c3fac8a8426f755b1" + integrity sha512-4s+5YWu4s7UblZVd6RQ+4foMs1km+QVdP04DtXNyja/5od9312EgLlgNOXszmbbw+7t/y7XkTBGA8ADtcpOdMQ== fs-extra@^10.0.0: version "10.0.0" @@ -160,10 +330,30 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-intrinsic@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -176,11 +366,35 @@ get-port@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" +glob-parent@~5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" @@ -195,6 +409,24 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + ip@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -205,10 +437,49 @@ is-arguments@^1.0.4: dependencies: call-bind "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-date-object@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.4.tgz#550cfcc03afada05eea3dd30981c7b09551f73e5" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-regex@^1.0.4: version "1.1.3" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" @@ -216,6 +487,23 @@ is-regex@^1.0.4: call-bind "^1.0.2" has-symbols "^1.0.2" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -225,9 +513,20 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -logger@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/logger/-/logger-0.0.1.tgz#cb08171f8a6f6f674b8499dadf50bed4befb72c4" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" matcher-collection@^2.0.1: version "2.0.1" @@ -237,18 +536,59 @@ matcher-collection@^2.0.1: "@types/minimatch" "^3.0.3" minimatch "^3.0.2" -minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" +mocha@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.0.1.tgz#01e66b7af0012330c0a38c4b6eaa6d92b8a81bf9" + integrity sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.1" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.7" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.23" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.4" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + module-alias@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0" integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q== +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -260,11 +600,21 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +nanoid@3.1.23: + version "3.1.23" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== + neo-blessed@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/neo-blessed/-/neo-blessed-0.2.0.tgz#30f9495fdd104494402b62c6273a9c9b82de4f2b" integrity sha512-C2kC4K+G2QnNQFXUIxTQvqmrdSIzGTX1ZRKeDW6ChmvPRw8rTkTEJzbEQHiHy06d36PCl/yMOCjquCRV8SpSQw== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -276,10 +626,65 @@ object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + printable-characters@^1.0.42: version "1.0.42" resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + regexp.prototype.flags@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" @@ -287,14 +692,69 @@ regexp.prototype.flags@^1.2.0: call-bind "^1.0.2" define-properties "^1.1.3" -safe-buffer@^5.0.1: +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +safe-buffer@^5.0.1, safe-buffer@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" @@ -305,6 +765,18 @@ thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + typescript@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" @@ -328,11 +800,87 @@ walk-sync@^3.0.0: matcher-collection "^2.0.1" minimatch "^3.0.4" +which@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +workerpool@6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.4.tgz#6a972b6df82e38d50248ee2820aa98e2d0ad3090" + integrity sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + ws@^7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yarn@^1.22.10: version "1.22.10" resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==