diff --git a/.vscode/settings.json b/.vscode/settings.json index f83120c..e9ae4c5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,25 +1,26 @@ { "workbench.colorCustomizations": { - "activityBar.activeBackground": "#d2d1f5", - "activityBar.background": "#d2d1f5", + "activityBar.activeBackground": "#83a0ea", + "activityBar.background": "#83a0ea", "activityBar.foreground": "#15202b", "activityBar.inactiveForeground": "#15202b99", - "activityBarBadge.background": "#dd6562", + "activityBarBadge.background": "#fae4ea", "activityBarBadge.foreground": "#15202b", - "commandCenter.border": "#15202b99", - "sash.hoverBorder": "#d2d1f5", - "statusBar.background": "#a9a7ec", - "statusBar.foreground": "#15202b", - "statusBarItem.hoverBackground": "#807de3", - "statusBarItem.remoteBackground": "#a9a7ec", - "statusBarItem.remoteForeground": "#15202b", - "titleBar.activeBackground": "#a9a7ec", - "titleBar.activeForeground": "#15202b", - "titleBar.inactiveBackground": "#a9a7ec99", - "titleBar.inactiveForeground": "#15202b99" + "commandCenter.border": "#e7e7e799", + "sash.hoverBorder": "#83a0ea", + "statusBar.background": "#577ee3", + "statusBar.foreground": "#e7e7e7", + "statusBarItem.hoverBackground": "#83a0ea", + "statusBarItem.remoteBackground": "#577ee3", + "statusBarItem.remoteForeground": "#e7e7e7", + "titleBar.activeBackground": "#577ee3", + "titleBar.activeForeground": "#e7e7e7", + "titleBar.inactiveBackground": "#577ee399", + "titleBar.inactiveForeground": "#e7e7e799" }, - "peacock.remoteColor": "#a9a7ec", + "peacock.remoteColor": "#577ee3", "deno.enable": true, "deno.unstable": true, - "deno.config": "./deno.jsonc" + "deno.config": "./deno.jsonc", + "svg.preview.background": "black" } \ No newline at end of file diff --git a/40kParsing/index.ts b/40kParsing/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/40kParsing/pdfParsing.ts b/40kParsing/pdfParsing.ts new file mode 100644 index 0000000..80708d2 --- /dev/null +++ b/40kParsing/pdfParsing.ts @@ -0,0 +1,24 @@ +import { PDFDocumentProxy, PDFPageProxy, getDocument } from 'npm:pdfjs-dist'; + +export async function parsePDF(pdfPath: string): Promise { + // Load the PDF file + const loadingTask = getDocument(pdfPath); + const pdf: PDFDocumentProxy = await loadingTask.promise; + + const numPages = pdf.numPages; + const textContent: string[] = []; + + // Iterate over each page and extract text content + for (let i = 1; i <= numPages; i++) { + const page: PDFPageProxy = await pdf.getPage(i); + const pageContent = await page.getTextContent(); + + // Extract text from the content items + const pageText = pageContent.items.map(item => item.str).join(' '); + textContent.push(pageText); + } + + // Combine the text content from all pages + return textContent.join('\n'); +} + diff --git a/constsAndEnums.ts b/common/constsAndEnums.ts similarity index 100% rename from constsAndEnums.ts rename to common/constsAndEnums.ts diff --git a/createMissingContainers.ts b/createMissingContainers.ts index a1b9447..ee16a7d 100644 --- a/createMissingContainers.ts +++ b/createMissingContainers.ts @@ -1,3 +1,5 @@ +import {parse, stringify} from 'yaml'; + for await (const service of Deno.readDir('.')) { if (service.isFile || !service.name.includes('-service')) continue; @@ -11,7 +13,7 @@ ${port ? 'EXPOSE ' + port : ''} WORKDIR /${serviceName} -ADD ./user-service . +ADD ${serviceFile} . COPY ./deno.jsonc . COPY ./secrets.json . COPY ./key.txt . @@ -19,6 +21,16 @@ ADD ./common ./common ADD ./lib ./lib ADD ./middleware ./middleware -CMD ["run", "${perms.join('", "')}", main.ts${port ? `, "${port}"` : ''}] +CMD ["run", "${perms.join('", "')}", "main.ts"${port ? `, "${port}"` : ''}] `); + + const dockerCompose: any = parse(await Deno.readTextFile('./docker-compose.yml')); + dockerCompose['services'][serviceName] = { + build: { + context: "./", + dockerfile: serviceFile + 'Dockerfile' + } + } + + await Deno.writeTextFile('./docker-compose.yml', stringify(dockerCompose)) } \ No newline at end of file diff --git a/createService.ts b/createService.ts index 72b86b3..e94acd4 100644 --- a/createService.ts +++ b/createService.ts @@ -85,10 +85,12 @@ import { Router } from 'oak'; const app = new CGGService({ prefix: '/${serviceName}' }); -app.route(new Router()); +app.route(new Router() + .get('/', ctx => ctx.response.body = '${serviceName} service') +); app.start(); -console.log('User service running on ' + Deno.args.at(0)); +console.log('${serviceName} service running on ' + Deno.args.at(0)); `); await Deno.writeTextFile(serviceFile + 'perms', perms.map(p => p.denoPerm).join('\n')); await Deno.writeTextFile(serviceFile + 'prefix', serviceName); @@ -100,16 +102,26 @@ ${port ? 'EXPOSE ' + port : ''} WORKDIR /${serviceName} -ADD ./user-service . -COPY ./deno.jsonc . -COPY ./secrets.json . -COPY ./key.txt . +ADD ${serviceFile} . +ADD ./deno.jsonc . +ADD ./secrets.json . +ADD ./key.txt . ADD ./common ./common ADD ./lib ./lib ADD ./middleware ./middleware CMD ["run", "${perms.join('", "')}", main.ts${port ? `, "${port}"` : ''}] `); + + const dockerCompose: any = parse(await Deno.readTextFile('./docker-compose.yml')); + dockerCompose['services'][serviceName] = { + build: { + context: "./", + dockerfile: serviceFile + 'Dockerfile' + } + } + + await Deno.writeTextFile('./docker-compose.yml', stringify(dockerCompose)) } if (confirm('Does this service need DB access?')) diff --git a/deno.jsonc b/deno.jsonc index c3752de..c70ca11 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -2,7 +2,7 @@ "imports": { "oak": "https://deno.land/x/oak@v12.2.0/mod.ts", "mongoose": "npm:mongoose", - "yaml": "npm:yaml", + "yaml": "https://deno.land/std@0.186.0/yaml/mod.ts", "/": "./", "./": "./", "common/": "./common/", diff --git a/deno.lock b/deno.lock index b186b31..05654d2 100644 --- a/deno.lock +++ b/deno.lock @@ -348,6 +348,46 @@ "https://deno.land/std@0.183.0/streams/writer_from_stream_writer.ts": "07c7ee025151a190f37fc42cbb01ff93afc949119ebddc6e0d0df14df1bf6950", "https://deno.land/std@0.183.0/streams/zip_readable_streams.ts": "a9d81aa451240f79230add674809dbee038d93aabe286e2d9671e66591fc86ca", "https://deno.land/std@0.183.0/types.d.ts": "dbaeb2c4d7c526db9828fc8df89d8aecf53b9ced72e0c4568f97ddd8cda616a4", + "https://deno.land/std@0.186.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", + "https://deno.land/std@0.186.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219", + "https://deno.land/std@0.186.0/io/buffer.ts": "17f4410eaaa60a8a85733e8891349a619eadfbbe42e2f319283ce2b8f29723ab", + "https://deno.land/std@0.186.0/types.d.ts": "dbaeb2c4d7c526db9828fc8df89d8aecf53b9ced72e0c4568f97ddd8cda616a4", + "https://deno.land/std@0.186.0/yaml/_dumper/dumper.ts": "a2c937a53a2b0473125a31a330334cc3f30e98fd82f8143bc225583d1260890b", + "https://deno.land/std@0.186.0/yaml/_dumper/dumper_state.ts": "f0d0673ceea288334061ca34b63954c2bb5feb5bf6de5e4cfe9a942cdf6e5efe", + "https://deno.land/std@0.186.0/yaml/_error.ts": "b59e2c76ce5a47b1b9fa0ff9f96c1dd92ea1e1b17ce4347ece5944a95c3c1a84", + "https://deno.land/std@0.186.0/yaml/_loader/loader.ts": "04cf748a736a9b3a29bd3d4b3c77d81489f82cfe8391627fd6ba8327e1e8cec2", + "https://deno.land/std@0.186.0/yaml/_loader/loader_state.ts": "0841870b467169269d7c2dfa75cd288c319bc06f65edd9e42c29e5fced91c7a4", + "https://deno.land/std@0.186.0/yaml/_mark.ts": "dcd8585dee585e024475e9f3fe27d29740670fb64ebb970388094cad0fc11d5d", + "https://deno.land/std@0.186.0/yaml/_state.ts": "ef03d55ec235d48dcfbecc0ab3ade90bfae69a61094846e08003421c2cf5cfc6", + "https://deno.land/std@0.186.0/yaml/_type/binary.ts": "d34d8c8d8ed521e270cfede3401c425b971af4f6c69da1e2cb32b172d42c7da7", + "https://deno.land/std@0.186.0/yaml/_type/bool.ts": "5bfa75da84343d45347b521ba4e5aeace9fe6f53447405290d53315a3fc20e66", + "https://deno.land/std@0.186.0/yaml/_type/float.ts": "056bd3cb9c5586238b20517511014fb24b0e36f98f9f6073e12da308b6b9808a", + "https://deno.land/std@0.186.0/yaml/_type/function.ts": "ff574fe84a750695302864e1c31b93f12d14ada4bde79a5f93197fc33ad17471", + "https://deno.land/std@0.186.0/yaml/_type/int.ts": "563ad074f0fa7aecf6b6c3d84135bcc95a8269dcc15de878de20ce868fd773fa", + "https://deno.land/std@0.186.0/yaml/_type/map.ts": "7b105e4ab03a361c61e7e335a0baf4d40f06460b13920e5af3fb2783a1464000", + "https://deno.land/std@0.186.0/yaml/_type/merge.ts": "8192bf3e4d637f32567917f48bb276043da9cf729cf594e5ec191f7cd229337e", + "https://deno.land/std@0.186.0/yaml/_type/mod.ts": "060e2b3d38725094b77ea3a3f05fc7e671fced8e67ca18e525be98c4aa8f4bbb", + "https://deno.land/std@0.186.0/yaml/_type/nil.ts": "606e8f0c44d73117c81abec822f89ef81e40f712258c74f186baa1af659b8887", + "https://deno.land/std@0.186.0/yaml/_type/omap.ts": "cfe59a294726f5cea705c39a61fd2b08199cf48f4ccd6b040cb550ec0f38d0a1", + "https://deno.land/std@0.186.0/yaml/_type/pairs.ts": "0032fdfe57558d21696a4f8cf5b5cfd1f698743177080affc18629685c905666", + "https://deno.land/std@0.186.0/yaml/_type/regexp.ts": "1ce118de15b2da43b4bd8e4395f42d448b731acf3bdaf7c888f40789f9a95f8b", + "https://deno.land/std@0.186.0/yaml/_type/seq.ts": "95333abeec8a7e4d967b8c8328b269e342a4bbdd2585395549b9c4f58c8533a2", + "https://deno.land/std@0.186.0/yaml/_type/set.ts": "f28ba44e632ef2a6eb580486fd47a460445eeddbdf1dbc739c3e62486f566092", + "https://deno.land/std@0.186.0/yaml/_type/str.ts": "a67a3c6e429d95041399e964015511779b1130ea5889fa257c48457bd3446e31", + "https://deno.land/std@0.186.0/yaml/_type/timestamp.ts": "706ea80a76a73e48efaeb400ace087da1f927647b53ad6f754f4e06d51af087f", + "https://deno.land/std@0.186.0/yaml/_type/undefined.ts": "94a316ca450597ccbc6750cbd79097ad0d5f3a019797eed3c841a040c29540ba", + "https://deno.land/std@0.186.0/yaml/_utils.ts": "26b311f0d42a7ce025060bd6320a68b50e52fd24a839581eb31734cd48e20393", + "https://deno.land/std@0.186.0/yaml/mod.ts": "28ecda6652f3e7a7735ee29c247bfbd32a2e2fc5724068e9fd173ec4e59f66f7", + "https://deno.land/std@0.186.0/yaml/parse.ts": "1fbbda572bf3fff578b6482c0d8b85097a38de3176bf3ab2ca70c25fb0c960ef", + "https://deno.land/std@0.186.0/yaml/schema.ts": "96908b78dc50c340074b93fc1598d5e7e2fe59103f89ff81e5a49b2dedf77a67", + "https://deno.land/std@0.186.0/yaml/schema/core.ts": "fa406f18ceedc87a50e28bb90ec7a4c09eebb337f94ef17468349794fa828639", + "https://deno.land/std@0.186.0/yaml/schema/default.ts": "0047e80ae8a4a93293bc4c557ae8a546aabd46bb7165b9d9b940d57b4d88bde9", + "https://deno.land/std@0.186.0/yaml/schema/extended.ts": "0784416bf062d20a1626b53c03380e265b3e39b9409afb9f4cb7d659fd71e60d", + "https://deno.land/std@0.186.0/yaml/schema/failsafe.ts": "d219ab5febc43f770917d8ec37735a4b1ad671149846cbdcade767832b42b92b", + "https://deno.land/std@0.186.0/yaml/schema/json.ts": "5f41dd7c2f1ad545ef6238633ce9ee3d444dfc5a18101e1768bd5504bf90e5e5", + "https://deno.land/std@0.186.0/yaml/schema/mod.ts": "4472e827bab5025e92bc2eb2eeefa70ecbefc64b2799b765c69af84822efef32", + "https://deno.land/std@0.186.0/yaml/stringify.ts": "fffc09c65c68d3d63f8159e8cbaa3f489bc20a8e55b4fbb61a8c2e9f914d1d02", + "https://deno.land/std@0.186.0/yaml/type.ts": "1aabb8e0a3f4229ce0a3526256f68826d9bdf65a36c8a3890ead8011fcba7670", "https://deno.land/std@0.61.0/encoding/utf8.ts": "8654fa820aa69a37ec5eb11908e20b39d056c9bf1c23ab294303ff467f3d50a1", "https://deno.land/std@0.93.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58", "https://deno.land/std@0.93.0/_util/os.ts": "e282950a0eaa96760c0cf11e7463e66babd15ec9157d4c9ed49cc0925686f6a7", @@ -440,6 +480,18 @@ "https://deno.land/x/crypt@v0.1.0/src/base64.ts": "a9df3135c7b3ddedb4a839715f69b029dd322b342589df079e0c660e39bb3088", "https://deno.land/x/crypt@v0.1.0/src/bcrypt/bcrypt.ts": "ba4c04eefba74415d094d57f08694fdc71b552956241d5a442cd167fd828a1af", "https://deno.land/x/crypt@v0.1.0/src/bcrypt/mod.ts": "8ed6d792a8fa46568933a09339ea6e322aad12ac2a961caf1365c95333ad68da", + "https://deno.land/x/crypto@v0.10.0/aes.ts": "0f4e5af07514a07d56ec01b2186c0153f13d6e00c26fc4e70692996af6280e48", + "https://deno.land/x/crypto@v0.10.0/block-modes.ts": "a7ef359649a2cf235451e80aed7a5fda612d92ca2b158bf2a724b32899f8e455", + "https://deno.land/x/crypto@v0.10.0/src/aes/consts.ts": "582aeed7afda2fe3deac4a60c4a9f29c60a7fb66f56645f95fa0ddab49bde994", + "https://deno.land/x/crypto@v0.10.0/src/aes/mod.ts": "afa8c53d140a4f5c12d17ed03aef7f7d3186b3848f7ff4c73e9e758bba47b101", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/base.ts": "ed96f69c0855ffc2d34ffbab293ac131dd4fd3d24e6d8ccd86e2a2f9f898c9b5", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/cbc.ts": "ce1ae944dd1912febd1d69c26c3a4ba18caeac9544ac3c62abd8b2429842de19", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/cfb.ts": "95b937293e9daebd336370fd954a3c53e47853fc81e1574db1ea4f31c6eb4663", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/ctr.ts": "06fd8e338dbda0a6a7fa49718a0fd247830759820e61646a6cf611ad69a9d464", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/ecb.ts": "c346d692f16f8efbcc041c25dd761ca223ef92e03bb05457908953bf261ba325", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/mod.ts": "bb7e3ddafa15b1ca024b4b5013b23d134410d01e90ce3d5be5489eb9d5f601c5", + "https://deno.land/x/crypto@v0.10.0/src/block-modes/ofb.ts": "0f77075505853b4ba1a55b4edecb17323f8a1489456a3d3b74717565cccbf2ef", + "https://deno.land/x/crypto@v0.10.0/src/utils/padding.ts": "db60b542bf7629fada4a9b92dbae7fcfc7d074a325f3b4e6d5a269b16546aa9b", "https://deno.land/x/djwt@v2.8/algorithm.ts": "fa4c7354ab9f4808d38104fdc6f21c8270f65f109ed84136d4fe31a4504426d4", "https://deno.land/x/djwt@v2.8/deps.ts": "261b7b6bfe2602329d8f9de2938c2a898cd6dfa746b3454ae415df2c53e6ae4d", "https://deno.land/x/djwt@v2.8/mod.ts": "7abba8518688e88648882a95161b42391ac6043c142b1ab491b36f712189e1e1", diff --git a/docker-compose.yml b/docker-compose.yml index d3e5ce1..5906579 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ version: '3.9' services: - nginx: + nginx: image: 'jc21/nginx-proxy-manager:latest' restart: unless-stopped ports: @@ -8,10 +8,17 @@ services: - '81:81' - '443:443' volumes: - - ./data:/data - - ./letsencrypt:/etc/letsencrypt + - './data:/data' + - './letsencrypt:/etc/letsencrypt' user: - build: + build: context: ./ dockerfile: ./user-service/Dockerfile - + rules: + build: + context: ./ + dockerfile: ./rules-service/Dockerfile + game-systems: + build: + context: ./ + dockerfile: ./game-systems-service/Dockerfile diff --git a/game-systems-service/Dockerfile b/game-systems-service/Dockerfile index 65431c0..09cca02 100644 --- a/game-systems-service/Dockerfile +++ b/game-systems-service/Dockerfile @@ -4,7 +4,7 @@ EXPOSE 6903 WORKDIR /game-systems -ADD ./user-service . +ADD ./game-systems-service/ . COPY ./deno.jsonc . COPY ./secrets.json . COPY ./key.txt . @@ -12,4 +12,4 @@ ADD ./common ./common ADD ./lib ./lib ADD ./middleware ./middleware -CMD ["run", "--allow-net", "--allow-read", "--allow-write", main.ts, "6903"] +CMD ["run", "--allow-net", "--allow-read", "--allow-write", "--allow-env", "main.ts", "6903"] diff --git a/game-systems-service/key.txt b/game-systems-service/key.txt new file mode 100644 index 0000000..53d4144 --- /dev/null +++ b/game-systems-service/key.txt @@ -0,0 +1 @@ +{"kty":"oct","k":"8Wrvb6Sb0XTbL-qklscCDurI-yynKakHa6rGISTEgM77Za1cSvcWuOkWPNoaf395sEo1_uxe071IR2v6K4nfr5jbXQL20aGIcvhZeuBm-ATTZNvNuUqHTuRNJyFyw9hqUEQ62W-WvX78L15HCVFSuGd21WCHxtsJ9oUofPXto34","alg":"HS512","key_ops":["sign","verify"],"ext":true} \ No newline at end of file diff --git a/game-systems-service/main.ts b/game-systems-service/main.ts index 1b9aaa1..98dab11 100644 --- a/game-systems-service/main.ts +++ b/game-systems-service/main.ts @@ -4,7 +4,9 @@ import { Router } from 'oak'; const app = new CGGService({ prefix: '/game-systems' }); -app.route(new Router()); +app.route(new Router() + .get('/', ctx => ctx.response.body = 'game-systems service') +); app.start(); -console.log('User service running on ' + Deno.args.at(0)); +console.log('game-systems service running on ' + Deno.args.at(0)); diff --git a/game-systems-service/perms b/game-systems-service/perms index 351854e..b442cf2 100644 --- a/game-systems-service/perms +++ b/game-systems-service/perms @@ -1,3 +1,4 @@ --allow-net --allow-read ---allow-write \ No newline at end of file +--allow-write +--allow-env \ No newline at end of file diff --git a/game-systems-service/types/schema.ts b/game-systems-service/types/schema.ts new file mode 100644 index 0000000..bef7e7e --- /dev/null +++ b/game-systems-service/types/schema.ts @@ -0,0 +1,55 @@ +import { JSONArray, JSONObject, searchJSON } from "../../lib/JSONSearch/jsonSearch.ts"; + +export interface ISchema { + name: string; + accolades: any; // TODO - populate with accolades schema type + publicationRules: { + name: string; + isExtensible: boolean; + // overwrites: boolean; + canExtend: boolean; + reviewRequired: boolean; + corrections: { + reviewRequired: boolean; + preserveHistory: boolean; + } + }[] + allowsListBuilding: boolean; + listBuildingRules: any; // TODO - populate with list building rules schema type + schemaProperties: Record; +} + +// export type searchString = `${/[a-z]/i}` + +export class GameSystemSchema implements ISchema { + name: string; + accolades: any; + publicationRules: { + name: string; + isExtensible: boolean; + // overwrites: boolean; + canExtend: boolean; + reviewRequired: boolean; + corrections: { + reviewRequired: boolean; + preserveHistory: boolean; + }; + }[]; + allowsListBuilding: boolean; + listBuildingRules: any; + + schemaProperties: Record; + + constructor(schemaJson: ISchema) { + this.name = schemaJson.name; + this.accolades = schemaJson.accolades; + this.publicationRules = schemaJson.publicationRules; + this.allowsListBuilding = schemaJson.allowsListBuilding; + this.listBuildingRules = schemaJson.listBuildingRules; + this.schemaProperties = schemaJson.schemaProperties; + } + + search(search: string, values: T) { + return searchJSON(values, search); + } +} diff --git a/game-systems-service/types/schemaTest.ts b/game-systems-service/types/schemaTest.ts new file mode 100644 index 0000000..449937c --- /dev/null +++ b/game-systems-service/types/schemaTest.ts @@ -0,0 +1,292 @@ +import { GameSystemSchema } from "./schema.ts"; + +const schemaJson = [ + { + "_id": "6454820f30920b2262cd6640", + "index": 0, + "guid": "52724d58-ce75-4743-b6a9-8ae02b4a7450", + "isActive": false, + "balance": "$1,008.96", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "brown", + "name": "Taylor Bell", + "gender": "female", + "company": "FROSNEX", + "email": "taylorbell@frosnex.com", + "phone": "+1 (857) 459-2766", + "address": "787 Brooklyn Avenue, Hiko, Florida, 6808", + "about": "Ad ad cupidatat ea irure Lorem fugiat laboris exercitation consectetur in ea et. Quis do enim labore velit tempor voluptate ipsum proident aliqua ex excepteur exercitation. Pariatur aute nisi commodo eiusmod velit. Sit eu proident do minim culpa nulla veniam. Ipsum proident tempor nostrud exercitation occaecat sit est laborum officia do.\r\n", + "registered": "2020-11-14T02:52:36 +07:00", + "latitude": -42.333547, + "longitude": -158.109059, + "tags": [ + "proident", + "officia", + "cillum", + "proident", + "tempor", + "exercitation", + "Lorem" + ], + "friends": [ + { + "id": 0, + "name": "Fulton Greer" + }, + { + "id": 1, + "name": "Hubbard Glass" + }, + { + "id": 2, + "name": "Burt Carr" + } + ], + "greeting": "Hello, Taylor Bell! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "6454820fc0e3a34b70195552", + "index": 1, + "guid": "8e71b785-ad4d-4e12-a513-7385a9ba8286", + "isActive": true, + "balance": "$1,911.49", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "green", + "name": "Dianna Howard", + "gender": "female", + "company": "ZILLANET", + "email": "diannahoward@zillanet.com", + "phone": "+1 (962) 507-2555", + "address": "348 Woods Place, Floris, Oklahoma, 3814", + "about": "Officia enim aute proident tempor culpa mollit exercitation nulla. Commodo culpa ipsum ex laboris. Consequat nisi est incididunt sunt occaecat qui exercitation deserunt non et tempor. Ipsum voluptate anim veniam irure ad aute id magna sit anim non consectetur ipsum proident. Magna officia exercitation exercitation pariatur laborum proident.\r\n", + "registered": "2019-01-03T10:15:04 +07:00", + "latitude": -22.630118, + "longitude": 33.280088, + "tags": [ + "aute", + "nisi", + "labore", + "deserunt", + "nisi", + "dolore", + "excepteur" + ], + "friends": [ + { + "id": 1, + "name": "Whitney Hanson" + }, + { + "id": 2, + "name": "Brewer Ball" + } + ], + "greeting": "Hello, Dianna Howard! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "6454820f92d45ff55d79f55f", + "index": 2, + "guid": "bd42ca2d-3a82-4b80-82e6-43346611ba25", + "isActive": false, + "balance": "$2,100.03", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Montoya Sharp", + "gender": "male", + "company": "SENTIA", + "email": "montoyasharp@sentia.com", + "phone": "+1 (909) 447-3348", + "address": "773 Homecrest Avenue, Brambleton, Maine, 4567", + "about": "Mollit duis commodo reprehenderit commodo exercitation occaecat veniam in. Excepteur quis deserunt aliqua sit Lorem. Fugiat dolore nulla sint proident commodo ullamco consectetur. Fugiat do eiusmod adipisicing tempor cupidatat. Consectetur tempor magna ex officia aute eiusmod. Sunt ut laboris magna eiusmod commodo voluptate cupidatat in. Eiusmod aliqua proident aliquip ex tempor duis excepteur irure dolor cillum do.\r\n", + "registered": "2014-09-21T03:51:32 +06:00", + "latitude": 44.616264, + "longitude": 12.645741, + "tags": [ + "fugiat", + "nulla", + "nulla", + "commodo", + "amet", + "enim", + "anim" + ], + "friends": [ + { + "id": 1, + "name": "Wynn Mathews" + }, + { + "id": 2, + "name": "Love Cook" + } + ], + "greeting": "Hello, Montoya Sharp! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "6454820f75a0b1fd48ee40d1", + "index": 3, + "guid": "385bb445-c07f-40d6-b7ab-42c9b4c88903", + "isActive": false, + "balance": "$1,883.35", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "brown", + "name": "Marsh Parrish", + "gender": "male", + "company": "SEALOUD", + "email": "marshparrish@sealoud.com", + "phone": "+1 (954) 529-2585", + "address": "138 Ebony Court, Leeper, Federated States Of Micronesia, 9374", + "about": "Tempor esse et officia velit do in minim est eu enim. Ut irure Lorem cillum Lorem consequat proident in deserunt. Duis deserunt sit culpa ad aliqua quis. Incididunt amet dolore nostrud minim.\r\n", + "registered": "2020-12-30T01:05:12 +07:00", + "latitude": 65.637405, + "longitude": 24.894416, + "tags": [ + "quis", + "qui", + "consequat", + "esse", + "incididunt", + "aliquip", + "commodo" + ], + "friends": [ + { + "id": 1, + "name": "Gayle Mccarty" + }, + { + "id": 2, + "name": "Janet Mcleod" + } + ], + "greeting": "Hello, Marsh Parrish! You have 1 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "6454820f750a53838f37a442", + "index": 4, + "guid": "e5f25407-cc91-4976-87c2-f222af9e4817", + "isActive": false, + "balance": "$1,749.38", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "green", + "name": "Elvira Salinas", + "gender": "female", + "company": "ENTHAZE", + "email": "elvirasalinas@enthaze.com", + "phone": "+1 (957) 446-2769", + "address": "292 Dwight Street, Shrewsbury, Wyoming, 6008", + "about": "Aute nostrud labore id dolor amet deserunt. Lorem Lorem aliquip Lorem laborum ad ad officia adipisicing magna amet ipsum est aliquip. Sunt excepteur nulla nisi in magna ut minim enim ipsum nisi magna exercitation pariatur. Eu in et do ad quis ex excepteur do occaecat labore. Labore nulla occaecat consequat aliquip fugiat culpa labore magna aliqua. Aliqua cillum in et aliquip cupidatat Lorem eu pariatur dolore velit. Sint minim irure nostrud qui laborum fugiat sunt ex.\r\n", + "registered": "2018-07-31T10:42:54 +06:00", + "latitude": -22.4115, + "longitude": 3.726494, + "tags": [ + "cupidatat", + "duis", + "laborum", + "incididunt", + "et", + "in", + "sit" + ], + "friends": [ + { + "id": 1, + "name": "Alta Romero" + }, + { + "id": 2, + "name": "Christian Carrillo" + } + ], + "greeting": "Hello, Elvira Salinas! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "6454820f0aa22ca7285106c8", + "index": 5, + "guid": "9856b273-6ade-4847-8d8e-13b27b8ddb8b", + "isActive": false, + "balance": "$3,662.75", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "blue", + "name": "Pearlie Sims", + "gender": "female", + "company": "HONOTRON", + "email": "pearliesims@honotron.com", + "phone": "+1 (810) 452-2724", + "address": "435 Cadman Plaza, Mooresburg, Kentucky, 4520", + "about": "Consequat et quis laborum laborum enim cillum do quis officia pariatur. Pariatur consectetur cillum commodo cillum non tempor incididunt consectetur Lorem laborum nostrud. Ullamco non sunt fugiat eiusmod ea voluptate duis irure proident.\r\n", + "registered": "2020-03-24T07:59:59 +06:00", + "latitude": -58.432669, + "longitude": -6.30611, + "tags": [ + "sit", + "minim", + "ea", + "anim", + "sint", + "culpa", + "ea" + ], + "friends": [ + { + "id": 0, + "name": "Goodman Holmes" + }, + { + "id": 1, + "name": "Francesca Bowers" + }, + { + "id": 2, + "name": "Mona Chapman" + } + ], + "greeting": "Hello, Pearlie Sims! You have 2 unread messages.", + "favoriteFruit": "apple" + } +]; + +const SchemaSearch = new GameSystemSchema({ + name: 'Test Schema', + accolades: '', + allowsListBuilding: true, + listBuildingRules: '', + publicationRules: [], + schemaProperties: { + "_id": "id", + "index": "number", + "guid": "guid", + "isActive": "boolean", + "balance": "money", + "picture": "string", + "age": "number", + "eyeColor": "string", + "name": "string", + "gender": "string", + "company": "string", + "email": "email", + "phone": "phone", + "address": "string", + "about": "string", + "registered": "date", + "latitude": "number", + "longitude": "number", + "tags": ["string"], + "friends": ['.'], + "greeting": "string", + "favoriteFruit": "string" + } +}) + +console.log(SchemaSearch.search('friends[id=0]', schemaJson)); diff --git a/honors-service/Dockerfile b/honors-service/Dockerfile deleted file mode 100644 index c5572c5..0000000 --- a/honors-service/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ - -FROM denoland/deno:1.33.2 -EXPOSE 6902 - -WORKDIR /honors - -ADD ./user-service . -COPY ./deno.jsonc . -COPY ./secrets.json . -COPY ./key.txt . -ADD ./common ./common -ADD ./lib ./lib -ADD ./middleware ./middleware - -CMD ["run", "--allow-net", main.ts, "6902"] diff --git a/honors-service/data.ts b/honors-service/data.ts deleted file mode 100644 index bbc7894..0000000 --- a/honors-service/data.ts +++ /dev/null @@ -1,5 +0,0 @@ - -import mongoose from 'mongoose'; -import { configDatabase } from 'lib/data.ts'; - -configDatabase(mongoose); diff --git a/honors-service/main.ts b/honors-service/main.ts deleted file mode 100644 index 525b1b9..0000000 --- a/honors-service/main.ts +++ /dev/null @@ -1,10 +0,0 @@ - -import { CGGService } from 'cgg/Application.ts'; -import { Router } from 'oak'; - -const app = new CGGService({ prefix: '/honors' }); - -app.route(new Router()); - -app.start(); -console.log('User service running on ' + Deno.args.at(0)); diff --git a/honors-service/perms b/honors-service/perms deleted file mode 100644 index 129a934..0000000 --- a/honors-service/perms +++ /dev/null @@ -1 +0,0 @@ ---allow-net \ No newline at end of file diff --git a/honors-service/port b/honors-service/port deleted file mode 100644 index 1bf144c..0000000 --- a/honors-service/port +++ /dev/null @@ -1 +0,0 @@ -6902 \ No newline at end of file diff --git a/honors-service/prefix b/honors-service/prefix deleted file mode 100644 index b94ef62..0000000 --- a/honors-service/prefix +++ /dev/null @@ -1 +0,0 @@ -honors \ No newline at end of file diff --git a/lib/JSONSearch/jsonSearch.ts b/lib/JSONSearch/jsonSearch.ts new file mode 100644 index 0000000..c88fed0 --- /dev/null +++ b/lib/JSONSearch/jsonSearch.ts @@ -0,0 +1,182 @@ +export type JSONObject = { [key: string]: any }; +export type JSONArray = JSONObject[]; + +export function searchJSON(json: string | JSONObject | JSONArray, query: string): string | JSONArray | JSONObject | string[] | undefined { + if (typeof json === 'string') { + json = JSON.parse(json); + } + + const props = query.split('.'); + const currentArray: JSONArray = Array.isArray(json) ? json : [json]; + + for (let i = 0; i < currentArray.length; i++) { + let current = currentArray[i]; + + for (let j = 0; j < props.length; j++) { + const prop = props[j]; + // let isArrayQuery = false; + let arrayProp: string, arrayQuery: string | string[], arrayIndex: number; + + if (prop.includes('[') && prop.includes(']')) { + // isArrayQuery = true; + [arrayProp, arrayQuery] = prop.split(/[\[\]]/g).filter(Boolean); + + if (arrayQuery.includes('/')) { + arrayQuery = arrayQuery.split('/'); + } else { + arrayQuery = [arrayQuery]; + } + + arrayIndex = 0; + current = current[arrayProp][arrayIndex]; + while (current) { + if (checkArrayQuery(current, arrayQuery)) { + break; + } + current = current[arrayProp][++arrayIndex]; + } + } else { + current = current[prop]; + } + + if (current === undefined) { + break; + } + } + + if (current !== undefined) { + return current; + } + } + + return undefined; +} + +function checkArrayQuery(obj: JSONObject, queryArr: string[]): boolean { + return queryArr.every((query) => { + let [prop, operator, valueStr] = query.split(/([=!><]+)/); + prop = obj[prop]; + const values = valueStr.split('/'); + + if (values.length > 1) { + return values.includes(prop); + } + + switch (operator) { + case'=': + return areSimilar(prop, valueStr); + case '==': + return prop == valueStr; + case '!=': + return prop != valueStr; + case '>': + return prop > valueStr; + case '>=': + return prop >= valueStr; + case '<': + return prop < valueStr; + case '<=': + return prop <= valueStr; + case '><': + return includes(prop, valueStr); + default: + return false; + } + }); +} + +function areSimilar(val1: T, val2: T, tolerance = .05, useRatio?: boolean): boolean { + if ((typeof val1 === 'number' || isNaN(Number(val1))) && (typeof val2 === 'number' || isNaN(Number(val2)))) { + switch (!useRatio || val2 == 0) { + case true: { + return Math.abs(Number(val1) - Number(val2)) < tolerance; + } + case false: { + const ratio = Number(val1) / (Number(val2)) + return ratio >= 1 - tolerance && ratio <= 1 + tolerance; + } + } + } + + const v1 = val1.toString(); + const v2 = val2.toString(); + + const dist = levenshtein(v1, v2); + const diff = dist / ((v1.length + v2.length) / 2); + return useRatio ? diff <= 1 + tolerance && diff >= 1 - tolerance : diff <= Math.round(tolerance); +} + +function levenshtein(str1: string, str2: string): number { + const cost: number[][] = []; + const n = str1.length; + const m = str2.length; + let i, j; + + const minimum = (a: number, b: number, c: number) => { + let min = a; + if (b < min) { + min = b; + } + if (c < min) { + min = c; + } + return min; + } + + if (n == 0) { + return Infinity; + } + if (m == 0) { + return Infinity; + } + + for (let i = 0; i <= n; i++) { + cost[i] = []; + } + + for (i = 0; i <= n; i++) { + cost[i][0] = i; + } + + for (j = 0; j <= m; j++) { + cost[0][j] = j; + } + + for (i = 1; i <= n; i++) { + + const x = str1.charAt(i - 1); + + for (j = 1; j <= m; j++) { + + const y = str2.charAt(j - 1); + + if (x == y) { + + cost[i][j] = cost[i - 1][j - 1]; + + } else { + + cost[i][j] = 1 + minimum(cost[i - 1][j - 1], cost[i][j - 1], cost[i - 1][j]); + } + + }//endfor + + }//endfor + + return cost[n][m]; +} + +function includes(val1: T | T[], val2: T) { + if (Array.isArray(val1)) return val1.includes(val2); + else { + const v1 = val1.toString(); + const v2 = val2.toString(); + + return v1.includes(v2); + } +} + +function normalize(val: any) { + if (typeof val === 'string') return val.normalize(); + return val; +} diff --git a/lib/gsEncryption/index.ts b/lib/gsEncryption/index.ts new file mode 100644 index 0000000..420da9c --- /dev/null +++ b/lib/gsEncryption/index.ts @@ -0,0 +1,23 @@ +import {Aes} from "https://deno.land/x/crypto@v0.10.0/aes.ts"; +import {Cbc, Padding} from "https://deno.land/x/crypto@v0.10.0/block-modes.ts"; + +const te = new TextEncoder(); + +const key = te.encode("EmmaHasHugeTitts"); +const data = te.encode("DataToBeEncrypted"); +const iv = new Uint8Array(16); + +const cipher = new Cbc(Aes, key, iv, Padding.PKCS7) +const decipher = new Cbc(Aes, key, iv, Padding.PKCS7) + +const encrypted = cipher.encrypt(data); +const decrypted = decipher.decrypt(encrypted); + +console.decode = function (encoded: Uint8Array) { + const td = new TextDecoder(); + this.log(td.decode(encoded)); +} + +console.decode(data); +console.decode(encrypted); +console.decode(decrypted); diff --git a/lib/jwt.ts b/lib/jwt.ts index 033fc54..9d97847 100644 --- a/lib/jwt.ts +++ b/lib/jwt.ts @@ -4,7 +4,7 @@ let key: CryptoKey; try { const storedKey = Deno.readTextFileSync('./key.txt'); key = await crypto.subtle.importKey('jwk', JSON.parse(storedKey), {name: 'HMAC', hash: 'SHA-512'}, true, ['sign', 'verify']); -} catch (error) { +} catch (_) { key = await crypto.subtle.generateKey( { name: "HMAC", hash: {name: 'SHA-512'} }, true, diff --git a/project-warstone/.eslintrc.cjs b/project-warstone/.eslintrc.cjs new file mode 100644 index 0000000..4020bcb --- /dev/null +++ b/project-warstone/.eslintrc.cjs @@ -0,0 +1,14 @@ +module.exports = { + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': 'warn', + }, +} diff --git a/project-warstone/.gitignore b/project-warstone/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/project-warstone/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/project-warstone/index.html b/project-warstone/index.html new file mode 100644 index 0000000..aa781a0 --- /dev/null +++ b/project-warstone/index.html @@ -0,0 +1,13 @@ + + + + + + + BattleLog + + +
+ + + diff --git a/project-warstone/package.json b/project-warstone/package.json new file mode 100644 index 0000000..d6a311c --- /dev/null +++ b/project-warstone/package.json @@ -0,0 +1,34 @@ +{ + "name": "project-warstone", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@types/react-router-dom": "^5.3.3", + "autoprefixer": "^10.4.14", + "postcss": "^8.4.24", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.12.0", + "recoil": "^0.7.7", + "tailwindcss": "^3.3.2" + }, + "devDependencies": { + "@types/react": "^18.0.37", + "@types/react-dom": "^18.0.11", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "@vitejs/plugin-react-swc": "^3.0.0", + "eslint": "^8.38.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.3.4", + "typescript": "^5.0.2", + "vite": "^4.3.9" + } +} diff --git a/project-warstone/postcss.config.js b/project-warstone/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/project-warstone/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/project-warstone/public/battlelog icon.svg b/project-warstone/public/battlelog icon.svg new file mode 100644 index 0000000..f727b1e --- /dev/null +++ b/project-warstone/public/battlelog icon.svg @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/project-warstone/src/App.tsx b/project-warstone/src/App.tsx new file mode 100644 index 0000000..26fabc2 --- /dev/null +++ b/project-warstone/src/App.tsx @@ -0,0 +1,14 @@ +import { RecoilRoot } from 'recoil' +import { TextMapper } from './components/Importer/text-mapper' +import { SchemaBuilder } from './components/SchemaBuilder' + +function App() { + return ( + + {/* */} + + + ) +} + +export default App diff --git a/project-warstone/src/assets/react.svg b/project-warstone/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/project-warstone/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/project-warstone/src/components/AnimatedPageContainer/index.css b/project-warstone/src/components/AnimatedPageContainer/index.css new file mode 100644 index 0000000..e69de29 diff --git a/project-warstone/src/components/AnimatedPageContainer/index.tsx b/project-warstone/src/components/AnimatedPageContainer/index.tsx new file mode 100644 index 0000000..f381de5 --- /dev/null +++ b/project-warstone/src/components/AnimatedPageContainer/index.tsx @@ -0,0 +1,32 @@ +import React, { useState, useEffect, ReactNode, useRef, useLayoutEffect, useCallback } from 'react'; +import { FCC } from '../../types'; + +interface IProps { + currentPage: number; +} + +const AnimatedPageContainer: FCC = ({ children, currentPage }) => { + const [uuid] = useState(crypto.randomUUID()); + + const renderChild = (child: ReactNode, index: number) => { + const isActive = index === currentPage; + + return ( +
+ {child} +
+ ); + }; + + return ( +
+ {React.Children.map(children, renderChild)} +
+ ); +}; + +export default AnimatedPageContainer; diff --git a/project-warstone/src/components/Importer/text-mapper.tsx b/project-warstone/src/components/Importer/text-mapper.tsx new file mode 100644 index 0000000..9b0717c --- /dev/null +++ b/project-warstone/src/components/Importer/text-mapper.tsx @@ -0,0 +1,1066 @@ +import { useState, ChangeEvent, FormEvent, FC } from 'react'; + +// interface KeySelectionComponentProps {} + +export const TextMapper: FC = () => { + const text = ` + RIPPER SWARMS +M + +T + +SV + +W + +LD + +OC + +6" + +2 + +6+ + +4 + +8+ + +0 + +RANGED WEAPONS + +RANGE + +A + +BS + +S + +AP + +D + +ABILITIES + +Spinemaws [PISTOL] + +6" + +4 + +5+ + +3 + +0 + +1 + +CORE: Deep Strike + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +FACTION: Synapse + +Xenos claws and teeth [SUSTAINED HITS 1] + +Melee + +6 + +5+ + +2 + +0 + +1 + +Chitinous Horrors (Aura): While an enemy unit is within +Engagement Range of this unit, halve the Objective Control +characteristic of models in that enemy unit. + +KEYWORDS: Swarm, Great Devourer, Ripper Swarms + +FACTION KEYWORDS: +Tyranids + +RIPPER SWARMS +Living carpets of Rippers squirm across the ground wherever the +Tyranid swarms advance. Little more than simple eating machines, +these chitinous horrors swarm over the wounded and dead alike, and +can even drag down trained warriors in sufficient numbers. Once a +Ripper's fangs sink home, it will not let go… + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- All models in this unit can each be equipped with 1 spinemaws. + +- 3-6 Ripper Swarms +Every model is equipped with: xenos claws and teeth. + +KEYWORDS: Swarm, Great Devourer, Ripper Swarms + +FACTION KEYWORDS: +Tyranids + +SCREAMER-KILLER +M + +T + +SV + +W + +LD + +OC + +8" + +9 + +2+ + +10 + +8+ + +3 + +RANGED WEAPONS +Bio-plasmic scream [ASSAULT, BLAST] + +RANGE + +A + +BS + +S + +AP + +D + +ABILITIES + +18" + +D6+3 + +4+ + +8 + +-2 + +1 + +CORE: Deadly Demise 1 + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +FACTION: Synapse + +Screamer-killer talons + +Melee + +10 + +3+ + +10 + +-2 + +3 + +Death Scream: In your Shooting phase, after this model has +shot, select one unit hit by one or more of those attacks. +That unit must take a Battle-shock test, subtracting 1 from +that test. + +KEYWORDS: Monster, Great Devourer, Screamer-Killer + +FACTION KEYWORDS: +Tyranids + +SCREAMER-KILLER +An older adaptation of the basic Carnifex strain, the Screamer-Killer +was christened by terrified Imperial troops for the distinctive howl +it emits as it generates then unleashes its bio-plasmic blasts. +Screamer-Killers are often seen at the forefront of a Tyranid assault, +where they can inflict the most damage quickly. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 1 Screamer-Killer +This model is equipped with: bio-plasmic scream; +Screamer-Killer talons. + +KEYWORDS: Monster, Great Devourer, Screamer-Killer + +FACTION KEYWORDS: +Tyranids + +PSYCHOPHAGE +M + +T + +SV + +W + +LD + +OC + +8" + +9 + +3+ + +10 + +8+ + +3 + +RANGED WEAPONS +Psychoclastic torrent [IGNORES COVER, TORRENT] + +MELEE WEAPONS +Talons and betentacled maw +[ANTI-PSYKER 2+, DEVASTATING WOUNDS] + +RANGE + +A + +BS + +S + +AP + +D + +ABILITIES + +12" + +D6 + +N/A + +6 + +-1 + +1 + +CORE: Deadly Demise 1, Feel No Pain 5+ + +RANGE + +A + +WS + +S + +AP + +D + +FACTION: Synapse + +Melee + +D6+1 + +3+ + +6 + +-1 + +2 + +Bio-stimulus (Aura): While a friendly Tyranids unit +is within 6" of this model, models in that unit have the +Feel No Pain 6+ ability. +Feeding Frenzy: Each time this model makes a melee attack +that targets a unit that is below its Starting Strength, add 1 to +the Hit roll. If that target is also Below Half-strength, add 1 to +the Wound roll as well. + +KEYWORDS: Monster, Great Devourer, Psychophage + +FACTION KEYWORDS: +Tyranids + +PSYCHOPHAGE +These monsters stampede into battle with frightening speed. They +devour any prey organism in their paths, but especially favour those +victims with psychic abilities. How they metabolise such esoteric +powers is unclear, but doing so allows them to project surges of +psychocorrosive ash that deflagrate their victims' minds and souls. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 1 Psychophage +This model is equipped with: psychoclastic torrent; talons +and betentacled maw. + +KEYWORDS: Monster, Great Devourer, Psychophage + +FACTION KEYWORDS: +Tyranids + +BARBGAUNTS +M + +T + +SV + +W + +LD + +OC + +6" + +4 + +4+ + +2 + +8+ + +1 + +RANGED WEAPONS + +RANGE + +A + +BS + +S + +AP + +D + +ABILITIES + +Bio-cannon [BLAST, HEAVY] + +24" + +D6 + +4+ + +5 + +0 + +1 + +FACTION: Synapse + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +Xenos claws and teeth + +Melee + +1 + +4+ + +4 + +0 + +1 + +Disruption Bombardment: In your Shooting phase, after +this unit has shot, if an enemy Infantry unit was hit by one +or more of those attacks made by this unit's bio-cannons, +until the end of your opponent's next turn, that enemy unit is +disrupted. While a unit is disrupted, subtract 2 from its Move +characteristic, and subtract 2 from Advance and Charge rolls +made for it. + +KEYWORDS: Infantry, Great Devourer, Barbgaunts + +FACTION KEYWORDS: +Tyranids + +BARBGAUNTS +Barbgaunts are little more than living weapons, their bodies and +bio-cannons slaved to the will of a pulsating ganglio-parasite that +piggybacks them into battle. There, they unleash volleys of chitinous +barbs that detonate with the fury of violent muscle-spasms and +transfix nearby victims with hails of jagged projectiles. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 5-10 Barbgaunts +Every model is equipped with: bio-cannon; xenos claws +and teeth. + +KEYWORDS: Infantry, Great Devourer, Barbgaunts + +FACTION KEYWORDS: +Tyranids + +TERMAGANTS +M + +T + +SV + +W + +LD + +OC + +6" + +3 + +5+ + +1 + +8+ + +2 + +RANGED WEAPONS + +RANGE + +A + +BS + +S + +AP + +D + +ABILITIES + +Fleshborer [ASSAULT] + +18" + +1 + +4+ + +5 + +0 + +1 + +FACTION: Synapse + +Termagant spinefists [ASSAULT, PISTOL, TWIN-LINKED] + +12" + +2 + +4+ + +3 + +0 + +1 + +Termagant devourer + +18" + +2 + +4+ + +4 + +0 + +1 + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +Xenos claws and teeth + +Melee + +1 + +4+ + +3 + +0 + +1 + +KEYWORDS: Infantry, Great Devourer, Endless Multitude, Termagants + +Skulking Horrors: Once per turn, when an enemy unit ends a +Normal, Advance or Fall Back move within 9" of this unit, if this +unit is not within Engagement Range of one or more enemy +units, it can make a Normal move of up to D6". + +FACTION KEYWORDS: +Tyranids + +TERMAGANTS +Scuttling predators that attack in huge swarms, Termagants were +originally spawned to roam the tight arterial passages of hive ships +and hunt intruders. They harry their prey with a hail of firepower, +seeking always to outflank and envelop their victims as they erode +their numbers. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- All models in this unit can each have their fleshborer replaced with 1 Termagant devourer. + +- 10-20 Termagants + +- All models in this unit can each have their fleshborer replaced with 1 Termagant spinefists. + +Every model is equipped with: fleshborer; xenos claws +and teeth. + +KEYWORDS: Infantry, Great Devourer, Endless Multitude, Termagants + +FACTION KEYWORDS: +Tyranids + +NEUROTYRANT +M + +T + +SV + +W + +LD + +OC + +6" + +8 + +4+ + +9 + +7+ + +3 + +RANGED WEAPONS + +RANGE + +A + +BS + +S + +AP + +D + +ABILITIES + +18" + +2D6 + +N/A + +5 + +-1 + +2 + +CORE: Leader + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +FACTION: Synapse, Shadow in the Warp + +Neurotyrant claws and lashes + +Melee + +6 + +3+ + +5 + +0 + +1 + +Node Lash (Psychic): While this model is leading a unit, each +time a model in that unit makes an attack, add 1 to the Hit roll. +If the target is Battle-shocked, add 1 to the Wound roll as well. + +Psychic scream [IGNORES COVER, PSYCHIC, TORRENT] + +Psychic Terror (Psychic): If one or more Neurotyrants +from your army are on the battlefield when you unleash the +Shadow in the Warp, subtract 1 from the Battle-shock test +each enemy unit on the battlefield must take as a result. +Synaptic Relays: In your Command phase, you can select +up to two friendly Tyranids units within 12" of this model's +unit. Until the start of your next Command phase, the selected +units are always considered to be within Synapse Range of +your army. +Designer's Note: Place a Synaptic Relay token next to each selected unit to +remind you. + +INVULNERABLE SAVE +KEYWORDS: Monster, Character, Fly, Psyker, Great Devourer, Synapse, +Neurotyrant + +FACTION KEYWORDS: +Tyranids + +4+ + +NEUROTYRANT +The Shadow in the Warp radiating from this immensely powerful +psyker-analogue creeps in all directions, driving even non-psychic +prey organisms to screaming madness. As its foes writhe in agony, +the Neurotyrant guides the swarms around it to slaughter with +brutal efficiency. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 1 Neurotyrant +This model is equipped with: psychic scream; Neurotyrant +claws and lashes. + +LEADER +This model can be attached to the following units: +- Neurogaunts +- Tyrant Guard + +KEYWORDS: Monster, Character, Fly, Psyker, Great Devourer, Synapse, +Neurotyrant + +FACTION KEYWORDS: +Tyranids + +VON RYAN'S LEAPERS +M + +T + +SV + +W + +LD + +OC + +10" + +5 + +4+ + +3 + +8+ + +1 + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +ABILITIES + +Leaper's talons + +Melee + +6 + +3+ + +5 + +-1 + +1 + +CORE: Fights First, Infiltrators, Stealth +FACTION: Synapse +Pouncing Leap: You can target this unit with the Heroic +Intervention Stratagem for 0CP, and can do so even if +you have already used that Stratagem on a different unit +this phase. + +INVULNERABLE SAVE + +KEYWORDS: Infantry, Great Devourer, Von Ryan's Leapers + +FACTION KEYWORDS: +Tyranids + +6+ + +VON RYAN'S LEAPERS +Stealthy hunters and expert ambushers, Von Ryan's Leapers are swift, +agile and especially lethal when fighting in dense terrain. Akin to +living mines, they lie still at the optimum locations to cause as much +damage as possible. When they sense the perfect time to strike, they +butcher all around in a murderous frenzy. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 3-6 Von Ryan's Leapers +Every model is equipped with: Leaper's talons. + +KEYWORDS: Infantry, Great Devourer, Von Ryan's Leapers + +FACTION KEYWORDS: +Tyranids + +NEUROGAUNTS +M + +T + +SV + +W + +LD + +OC + +6" + +3 + +6+ + +1 + +8+ + +1 + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +ABILITIES + +Xenos claws and teeth + +Melee + +1 + +4+ + +3 + +0 + +1 + +FACTION: Synapse +Neurocytes: While this unit is within Synapse Range of your +army, it has the Synapse keyword. + +KEYWORDS: Infantry, Great Devourer, Endless Multitude, Neurogaunts + +FACTION KEYWORDS: +Tyranids + +NEUROGAUNTS +Neurogaunts scuttle forward in seething masses, driven on by the +parasitic neurocytes that cling to their backs. Their primary purpose is +to protect the synaptic node beasts coordinating invasion swarms. It +is a task they go about with single-minded savagery, slashing, biting +and giving their lives without an instant's hesitation. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 1-2 Neurogaunt Nodebeasts* +- 10-20 Neurogaunts +Every model is equipped with: xenos claws and teeth. +* This unit can only contain 2 Neurogaunt Nodebeasts if it contains +20 Neurogaunts. + +KEYWORDS: Infantry, Great Devourer, Endless Multitude, Neurogaunts + +FACTION KEYWORDS: +Tyranids + +WINGED TYRANID PRIME +M + +T + +SV + +W + +LD + +OC + +12" + +5 + +4+ + +6 + +7+ + +1 + +MELEE WEAPONS + +RANGE + +A + +WS + +S + +AP + +D + +ABILITIES + +Prime talons + +Melee + +6 + +2+ + +6 + +-1 + +2 + +CORE: Deep Strike, Leader +FACTION: Shadow in the Warp, Synapse +Alpha Warrior: While this model is leading a unit, +weapons equipped by models in that unit have the +[SUSTAINED HITS 1] ability. +Death Blow: If this model is destroyed by a melee attack, if it +has not fought this phase, roll one D6: on a 4+, do not remove +it from play. The destroyed model can fight after the attacking +model's unit has finished making its attacks, and is then +removed from play. + +KEYWORDS: Infantry, Character, Fly, Great Devourer, Synapse, +Winged Tyranid Prime + +FACTION KEYWORDS: +Tyranids +WINGED TYRANID PRIME +Tyranid Primes adapted for flight possess all the physical and synaptic +might of an alpha war-beast, while also boasting the frightening speed +and manoeuvrability imparted by huge leathery wings. Swooping +down into the midst of the foe, they rend and tear until nought remains +but corpses and fleeing prey. + +WARGEAR OPTIONS + +UNIT COMPOSITION + +- None + +- 1 Winged Tyranid Prime +This model is equipped with: Prime talons. + +LEADER +This model can be attached to the following units: +- Gargoyles +- Tyranid Warriors with melee Bio-weapons +- Tyranid Warriors with Ranged Bio-weapons + +KEYWORDS: Infantry, Character, Fly, Great Devourer, Synapse, +Winged Tyranid Prime + +FACTION KEYWORDS: +Tyranids + ` + const lineCount = (text: string) => text.split('\n').length + + const numberOfDigits = (num: number) => num.toString().length + + const lineCountDigits = numberOfDigits(lineCount(text)); + + return ( +
+ {text.split('\n').map((l, i) => ( +
+
{(i + 1).toString().padStart(lineCountDigits, '0')}
+
{l}
+
+ ))} +
+ ) +} diff --git a/project-warstone/src/components/SchemaBuilder/field-editor.tsx b/project-warstone/src/components/SchemaBuilder/field-editor.tsx new file mode 100644 index 0000000..0c861a4 --- /dev/null +++ b/project-warstone/src/components/SchemaBuilder/field-editor.tsx @@ -0,0 +1,53 @@ +import { FC, useCallback, useEffect } from 'react' +import { FieldType, FieldTypes, fieldTypeOptions, fieldTypesWithValues } from '../../types/schema' +import { useObjectStateWrapper } from '../../hooks/useObjectState'; +import { FieldTypeInput } from './field-type-input'; +import { InputBinder } from '../../types/inputBinder'; +import { ValueField } from './value-field'; + +interface IProps { + update: (arg: FieldType) => void; + field: FieldType; + fieldName: string; +} + +export const FieldEditor: FC = ({ update, field, fieldName }) => { + const { update: updateField, bindProperty, bindPropertyCheck } = useObjectStateWrapper(field, (e) => update(typeof e === 'function' ? e(field) : e)) + + const shouldShowValueField = useCallback(() => fieldTypesWithValues.includes(field.type) || field.isConstant, [field.isConstant, field.type]); + + useEffect(() => { + console.log(field.value); + }, [field]) + + return ( +
  • +

    {fieldName}

    + + {shouldShowValueField() && ( + // <> + // {field.type === FieldTypes.dice && ( + // + // )} + // {field.type === FieldTypes.type && ( + // + + // )} + // + + )} + +
  • + ) +} diff --git a/project-warstone/src/components/SchemaBuilder/field-type-input.tsx b/project-warstone/src/components/SchemaBuilder/field-type-input.tsx new file mode 100644 index 0000000..0ac0102 --- /dev/null +++ b/project-warstone/src/components/SchemaBuilder/field-type-input.tsx @@ -0,0 +1,23 @@ +import { useRecoilValue } from 'recoil'; +import { SchemaEditAtom } from '../../recoil/atoms/schema'; +import { FCC } from '../../types' +import { InputBinder } from '../../types/inputBinder' + +interface IProps { + bind: InputBinder +} + +export const FieldTypeInput: FCC = ({ bind }) => { + const Schema = useRecoilValue(SchemaEditAtom); + + return ( + <> + + + {Object.keys(Schema.types).map(k => ( + + ))} + + + ) +} \ No newline at end of file diff --git a/project-warstone/src/components/SchemaBuilder/index.tsx b/project-warstone/src/components/SchemaBuilder/index.tsx new file mode 100644 index 0000000..1805ae8 --- /dev/null +++ b/project-warstone/src/components/SchemaBuilder/index.tsx @@ -0,0 +1,45 @@ +import { FC, useCallback, useState } from 'react' +import AnimatedPageContainer from '../AnimatedPageContainer'; +import { TypeEditor } from './type-editor'; +import { useObjectState, useObjectStateWrapper } from '../../hooks/useObjectState'; +import { Schema, TypeType } from '../../types/schema'; +import { useInput } from '../../hooks/useInput'; +import { useRecoilState } from 'recoil'; +import { SchemaEditAtom } from '../../recoil/atoms/schema'; + + +export const SchemaBuilder: FC = () => { + const [schema, setSchema] = useRecoilState(SchemaEditAtom); + const {update: updateSchema} = useObjectStateWrapper(schema, setSchema); + + const {value: typeName, bind: bindTypeName, reset: resetTypeName} = useInput(''); + + const [pageNumber, setPageNumber] = useState(1); + + const saveType = useCallback((name: string, type: TypeType) => { + updateSchema(e => ({ + types: { + ...e.types, + } + })); + resetTypeName(); + }, [resetTypeName, updateSchema]); + + return ( +
    +
    + +
    +

    Add A Type

    + + +
    + +
    +
    +
    + {JSON.stringify(schema, null, 2)} +
    +
    + ) +} \ No newline at end of file diff --git a/project-warstone/src/components/SchemaBuilder/type-editor.tsx b/project-warstone/src/components/SchemaBuilder/type-editor.tsx new file mode 100644 index 0000000..a138c69 --- /dev/null +++ b/project-warstone/src/components/SchemaBuilder/type-editor.tsx @@ -0,0 +1,52 @@ +import { FC, useCallback } from 'react' +import { FCC } from '../../types' +import { FieldType, FieldTypes, TypeType } from '../../types/schema' +import { useObjectState } from '../../hooks/useObjectState'; +import { useInput } from '../../hooks/useInput'; +import { FieldEditor } from './field-editor'; + +interface IProps { + name: string; + saveType: (arg0: string, arg1: TypeType) => void; +} + +const constantProperties = ['metadata']; + +export const TypeEditor: FCC = ({ saveType, name }) => { + const { update: updateType, reset: resetType, state: type } = useObjectState({}); + + const { value: propertyName, setValue: setPropertyName, bind: bindPropertyName, reset: resetPropertyName } = useInput(''); + + const save = () => { + saveType(name, type); + resetType(); + } + + const addField = useCallback(() => { + updateType({ + [propertyName]: { + type: FieldTypes.number, + value: '', + isConstant: false, + limit: 1, + } + }) + }, [propertyName, updateType]) + + const updateField = useCallback((k: keyof typeof type) => (field: FieldType) => { + updateType({ [k]: field }) + }, [updateType]) + + return ( +
    +

    Creating type "{name}"

    + + +
      + {Object.entries(type).filter(([k]) => !constantProperties.includes(k)).map(([key, value]) => ( + + ))} +
    +
    + ) +} \ No newline at end of file diff --git a/project-warstone/src/components/SchemaBuilder/value-field.tsx b/project-warstone/src/components/SchemaBuilder/value-field.tsx new file mode 100644 index 0000000..9ba11f5 --- /dev/null +++ b/project-warstone/src/components/SchemaBuilder/value-field.tsx @@ -0,0 +1,37 @@ +import { FC } from 'react'; +import { FieldTypes } from '../../types/schema'; +import { InputBinder } from '../../types/inputBinder'; +import { FieldTypeInput } from './field-type-input'; + +interface IValueProps { + type: FieldTypes; + bind: InputBinder; +} + +const diceSides = [3, 4, 6, 8, 10, 12, 20, 100]; + +export const ValueField: FC = ({type, bind}) => { + switch (type) { + case FieldTypes.dice: + return ( + + ); + case FieldTypes.type: + return ( + + ) + case FieldTypes.number: + return ( + + ) + default: + return <>; + } +} diff --git a/project-warstone/src/hooks/useInput.ts b/project-warstone/src/hooks/useInput.ts new file mode 100644 index 0000000..907be3d --- /dev/null +++ b/project-warstone/src/hooks/useInput.ts @@ -0,0 +1,35 @@ +import { useState, ChangeEvent } from 'react'; + +export const useInput = (initialValue: T) => { + const [value, setValue] = useState(initialValue); + + return { + value, + setValue, + reset: () => setValue(initialValue), + bind: { + value: value, + onChange: (event: ChangeEvent) => { + const changed: string | number = typeof initialValue === 'number' ? parseInt(event.target.value) : event.target.value; + setValue(changed as T); + } + } + }; +}; + +export const useCheckbox = (initial: boolean) => { + const [value, setValue] = useState(initial); + + return { + value, + setValue, + reset: () => setValue(initial), + bind: { + checked: value, + onClick: () => { + setValue(v => !v); + }, + readOnly: true + } + }; +}; \ No newline at end of file diff --git a/project-warstone/src/hooks/useObjectState.ts b/project-warstone/src/hooks/useObjectState.ts new file mode 100644 index 0000000..6706a97 --- /dev/null +++ b/project-warstone/src/hooks/useObjectState.ts @@ -0,0 +1,84 @@ +import React, { ChangeEvent, useCallback, useState } from 'react'; +import { InputBinder } from '../types/inputBinder'; + +export const useObjectState = (initial: T) => { + const [state, setState] = useState(initial || {} as T); + + const bindProperty = useCallback((property: K) => ({ + value: state[property] ?? '', + name: property, + onChange: (event: ChangeEvent) => + setState(value => ( + { + ...value, + [event.target.name]: ( + (typeof value[property] === 'number') ? + Number(event.target.value) || 0 : + event.target.value) + } + )) + }), [state]) + + const bindPropertyCheck = useCallback((property: K) => ({ + checked: !!state[property], + name: property, + onChange: (event: ChangeEvent) => setState(value => ({ + ...value, [event.target.name]: (event.target.checked) + })), + readOnly: true + }), [state]) + + const update = useCallback((updates: Partial) => setState(s => ({ ...s, ...updates })), []) + + const reset = useCallback(() => { + setState(initial); + }, [initial]) + + return { + bindProperty, + bindPropertyCheck, + update, + state, + setState, + reset + } +} + +export const useObjectStateWrapper = (state: T, setState: React.Dispatch>) => { + + const bindProperty = useCallback((property: K): InputBinder => ({ + value: state[property] ?? '', + name: property.toString(), + onChange: (event: ChangeEvent) => + setState(value => ( + { + ...value, + [event.target.name]: ( + (typeof value[property] === 'number') ? + Number(event.target.value) || 0 : + event.target.value) + } + )) + }), [setState, state]) + + const bindPropertyCheck = useCallback((property: K) => ({ + checked: !!state[property], + name: property, + onChange: (event: ChangeEvent) => setState(value => ({ + ...value, [event.target.name]: (event.target.checked) + })), + readOnly: true + }), [setState, state]) + + const update = useCallback((updates: Partial | ((arg: T) => Partial)) => + setState(s => ({ ...s, ...(typeof updates === 'function' ? updates(s) : updates) } + )), [setState]) + + return { + bindProperty, + bindPropertyCheck, + update, + state, + setState + } +} \ No newline at end of file diff --git a/project-warstone/src/hooks/useQueryParams.ts b/project-warstone/src/hooks/useQueryParams.ts new file mode 100644 index 0000000..c167a48 --- /dev/null +++ b/project-warstone/src/hooks/useQueryParams.ts @@ -0,0 +1,10 @@ +import { useEffect, useRef } from 'react' +import { QueryParams } from '../utils/queryParams' + +export const useQueryParams = (options?: {clean: boolean}) => { + const queryParams = useRef(new QueryParams(options)) + + useEffect(() => { + console.log(queryParams.current.get('test')) + }, [queryParams.current]) +} \ No newline at end of file diff --git a/project-warstone/src/hooks/useRefCallback.ts b/project-warstone/src/hooks/useRefCallback.ts new file mode 100644 index 0000000..7685c68 --- /dev/null +++ b/project-warstone/src/hooks/useRefCallback.ts @@ -0,0 +1,19 @@ +import { ReactNode, useCallback, useRef } from 'react' + +export const useRefCallback = () : [T | null, (arg: T) => void] => { + const ref = useRef(null); + const setRef = useCallback((val: T) => { + console.log(val); + if (ref.current) { + // does something? + } + + if (val) { + // also does something? + } + + ref.current = val + }, []) + + return [ref.current, setRef] +} \ No newline at end of file diff --git a/project-warstone/src/index.css b/project-warstone/src/index.css new file mode 100644 index 0000000..5c4fdac --- /dev/null +++ b/project-warstone/src/index.css @@ -0,0 +1,39 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + @apply bg-bastille text-white + } + input, select { + @apply p-1 rounded-lg text-cinder-500 + } +} + +@layer components { + .panel { + @apply bg-cinder shadow-xl p-8 rounded-xl + } + .header { + @apply text-2xl font-bold + } + .subheader { + @apply text-xl font-bold + } + button { + @apply interactive bg-olive-drab p-1 + } +} + +@layer utilities { + .interactive { + @apply border-2 rounded-lg border-falcon cursor-pointer + } + .interactive svg { + @apply fill-falcon + } + .interactive:disabled { + @apply border-falcon-300 brightness-50 cursor-default + } +} diff --git a/project-warstone/src/main.tsx b/project-warstone/src/main.tsx new file mode 100644 index 0000000..91c03f3 --- /dev/null +++ b/project-warstone/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + , +) diff --git a/project-warstone/src/recoil/atoms/schema.ts b/project-warstone/src/recoil/atoms/schema.ts new file mode 100644 index 0000000..0599fec --- /dev/null +++ b/project-warstone/src/recoil/atoms/schema.ts @@ -0,0 +1,7 @@ +import { atom } from 'recoil'; +import { Schema, TypeType } from '../../types/schema'; + +export const SchemaEditAtom = atom({ + key: 'schema-edit', + default: {name: '', types: {}} +}); \ No newline at end of file diff --git a/project-warstone/src/services/game-systems.ts b/project-warstone/src/services/game-systems.ts new file mode 100644 index 0000000..e8aeaa2 --- /dev/null +++ b/project-warstone/src/services/game-systems.ts @@ -0,0 +1,24 @@ +import { Schema } from '../types/schema'; + +export const GameSystemsService = { + // todo - connect to service to save schema for game + saveSchema: async (schema: Schema) => { + localStorage.setItem('schema', JSON.stringify(schema)); + + return { status: 200 } + }, + // todo - connect to service to fetch schema for game + getSchema: async (id: string) => { + const schema = localStorage.getItem('schema'); + + if (schema) + return { + status: 200, + json: async () => JSON.parse(schema) + } + + return { + status: 404 + } + } +} \ No newline at end of file diff --git a/project-warstone/src/types.ts b/project-warstone/src/types.ts new file mode 100644 index 0000000..6eb985e --- /dev/null +++ b/project-warstone/src/types.ts @@ -0,0 +1,3 @@ +import { FC, PropsWithChildren } from "react"; + +export type FCC> = FC> \ No newline at end of file diff --git a/project-warstone/src/types/inputBinder.ts b/project-warstone/src/types/inputBinder.ts new file mode 100644 index 0000000..333c534 --- /dev/null +++ b/project-warstone/src/types/inputBinder.ts @@ -0,0 +1,7 @@ +import { ChangeEvent } from 'react' + +export type InputBinder = { + name: string, + value: string | number, + onChange: (e: ChangeEvent) => void +} \ No newline at end of file diff --git a/project-warstone/src/types/schema.ts b/project-warstone/src/types/schema.ts new file mode 100644 index 0000000..dbdf973 --- /dev/null +++ b/project-warstone/src/types/schema.ts @@ -0,0 +1,28 @@ +export type MetadataType = { + [key: string]: string +} + +export type FieldType = { + type: FieldTypes; + value: string; + isConstant: boolean; + limit: number; +}; + +export type TypeType = Record; + +export type Schema = { + name: string; + types: Record +} + +export enum FieldTypes { + number = 'number', + text = 'text', + checkbox = 'checkbox', + type = '@type', + dice = 'dice' +} + +export const fieldTypeOptions: (keyof typeof FieldTypes)[] = ['number', 'text', 'checkbox', 'type', 'dice'] +export const fieldTypesWithValues = [FieldTypes.dice, FieldTypes.type]; diff --git a/project-warstone/src/utils/queryParams.ts b/project-warstone/src/utils/queryParams.ts new file mode 100644 index 0000000..61e6dd0 --- /dev/null +++ b/project-warstone/src/utils/queryParams.ts @@ -0,0 +1,20 @@ +export class QueryParams { + private params = new Map() + constructor(options?: {clean: boolean}) { + if (!options?.clean) { + const {search} = location; + for (const [key, value] of search.replace('?', '').split('&').map(e => e.split('='))) { + this.params.set(key, value); + } + } + } + + get = this.params.get + set = this.params.set + delete = this.params.delete + clear = this.params.clear + + apply() { + location.search = '?' + encodeURIComponent(Array.from(this.params.entries()).map(e => e.join('=')).join('&')) + } +} \ No newline at end of file diff --git a/project-warstone/src/vite-env.d.ts b/project-warstone/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/project-warstone/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/project-warstone/tailwind.config.js b/project-warstone/tailwind.config.js new file mode 100644 index 0000000..009d817 --- /dev/null +++ b/project-warstone/tailwind.config.js @@ -0,0 +1,54 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + 'cinder': { + DEFAULT: '#120F16', + 50: '#6B5983', + 100: '#615177', + 200: '#4E415F', + 300: '#3A3047', + 400: '#26202E', + 500: '#120F16', + }, + 'falcon': { + DEFAULT: '#785474', + 50: '#9A6F95', + 100: '#90658B', + 200: '#785474', + 300: '#573D54', + 400: '#362634', + 500: '#150F14', + }, + 'bastille': { + DEFAULT: '#1A1420', + 50: '#765B91', + 100: '#6C5384', + 200: '#57436B', + 300: '#433352', + 400: '#2E2439', + 500: '#1A1420', + }, + 'olive-drab': { + DEFAULT: '#688E26', + 50: '#8BBE33', + 100: '#80AE2F', + 200: '#688E26', + 300: '#48621A', + 400: '#27350E', + 500: '#070902', + }, + }, + container: { + center: true + } + }, + }, + plugins: [], +} + diff --git a/project-warstone/tsconfig.json b/project-warstone/tsconfig.json new file mode 100644 index 0000000..a7fc6fb --- /dev/null +++ b/project-warstone/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/project-warstone/tsconfig.node.json b/project-warstone/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/project-warstone/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/project-warstone/vite.config.ts b/project-warstone/vite.config.ts new file mode 100644 index 0000000..1c782e9 --- /dev/null +++ b/project-warstone/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + appType: 'spa', + preview: { + port: 6969 + } +}) diff --git a/project-warstone/yarn.lock b/project-warstone/yarn.lock new file mode 100644 index 0000000..f4bd998 --- /dev/null +++ b/project-warstone/yarn.lock @@ -0,0 +1,1684 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + +"@esbuild/android-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" + integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== + +"@esbuild/android-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" + integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== + +"@esbuild/android-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" + integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== + +"@esbuild/darwin-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" + integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== + +"@esbuild/darwin-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" + integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== + +"@esbuild/freebsd-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" + integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== + +"@esbuild/freebsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" + integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== + +"@esbuild/linux-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" + integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== + +"@esbuild/linux-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" + integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== + +"@esbuild/linux-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" + integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== + +"@esbuild/linux-loong64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" + integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== + +"@esbuild/linux-mips64el@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" + integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== + +"@esbuild/linux-ppc64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" + integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== + +"@esbuild/linux-riscv64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" + integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== + +"@esbuild/linux-s390x@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" + integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== + +"@esbuild/linux-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" + integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== + +"@esbuild/netbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" + integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== + +"@esbuild/openbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" + integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== + +"@esbuild/sunos-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" + integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== + +"@esbuild/win32-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" + integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== + +"@esbuild/win32-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" + integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== + +"@esbuild/win32-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" + integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.5.2" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.42.0": + version "8.42.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6" + integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw== + +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@remix-run/router@1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.6.3.tgz#8205baf6e17ef93be35bf62c37d2d594e9be0dad" + integrity sha512-EXJysQ7J3veRECd0kZFQwYYd5sJMcq2O/m60zu1W2l3oVQ9xtub8jTOtYRE0+M2iomyG/W3Ps7+vp2kna0C27Q== + +"@swc/core-darwin-arm64@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.62.tgz#dafb50bf784c6b7b40dce6d8cf0605f6729812cb" + integrity sha512-MmGilibITz68LEje6vJlKzc2gUUSgzvB3wGLSjEORikTNeM7P8jXVxE4A8fgZqDeudJUm9HVWrxCV+pHDSwXhA== + +"@swc/core-darwin-x64@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.62.tgz#324bd144268860338040db64c42c2345fcaaebcf" + integrity sha512-Xl93MMB3sCWVlYWuQIB+v6EQgzoiuQYK5tNt9lsHoIEVu2zLdkQjae+5FUHZb1VYqCXIiWcULFfVz0R4Sjb7JQ== + +"@swc/core-linux-arm-gnueabihf@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.62.tgz#9b5ca188ea3c91827e43e4287bd20ce2a7cb7d81" + integrity sha512-nJsp6O7kCtAjTTMcIjVB0g5y1JNiYAa5q630eiwrnaHUusEFoANDdORI3Z9vXeikMkng+6yIv9/V8Rb093xLjQ== + +"@swc/core-linux-arm64-gnu@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.62.tgz#b208b005223fd9c4c4a12fc0e24070c5e902965f" + integrity sha512-XGsV93vpUAopDt5y6vPwbK1Nc/MlL55L77bAZUPIiosWD1cWWPHNtNSpriE6+I+JiMHe0pqtfS/SSTk6ZkFQVw== + +"@swc/core-linux-arm64-musl@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.62.tgz#bf66add093fa732d3b7f629e00b6ef9bf3c483f2" + integrity sha512-ESUmJjSlTTkoBy9dMG49opcNn8BmviqStMhwyeD1G8XRnmRVCZZgoBOKdvCXmJhw8bQXDhZumeaTUB+OFUKVXg== + +"@swc/core-linux-x64-gnu@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.62.tgz#b97eee374986388b71d87c67d7edb8208356dde2" + integrity sha512-wnHJkt3ZBrax3SFnUHDcncG6mrSg9ZZjMhQV9Mc3JL1x1s1Gy9rGZCoBNnV/BUZWTemxIBcQbANRSDut/WO+9A== + +"@swc/core-linux-x64-musl@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.62.tgz#548ccdef6d7535ee7fea6ec9488322411f10da1a" + integrity sha512-9oRbuTC/VshB66Rgwi3pTq3sPxSTIb8k9L1vJjES+dDMKa29DAjPtWCXG/pyZ00ufpFZgkGEuAHH5uqUcr1JQg== + +"@swc/core-win32-arm64-msvc@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.62.tgz#fc0ca735b23c017fe8ff6f85aa4788ddd1ac583d" + integrity sha512-zv14vlF2VRrxS061XkfzGjCYnOrEo5glKJjLK5PwUKysIoVrx/L8nAbFxjkX5cObdlyoqo+ekelyBPAO+4bS0w== + +"@swc/core-win32-ia32-msvc@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.62.tgz#f8dfbb4f0763d2db5ef420b04da3b5cb73897756" + integrity sha512-8MC/PZQSsOP2iA/81tAfNRqMWyEqTS/8zKUI67vPuLvpx6NAjRn3E9qBv7iFqH79iqZNzqSMo3awnLrKZyFbcw== + +"@swc/core-win32-x64-msvc@1.3.62": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.62.tgz#e661ec99c5ac91f1cd63c02b5f114f73f55e7b15" + integrity sha512-GJSmUJ95HKHZXAxiuPUmrcm/S3ivQvEzXhOZaIqYBIwUsm02vFZkClsV7eIKzWjso1t0+I/8MjrnUNaSWqh1rQ== + +"@swc/core@^1.3.61": + version "1.3.62" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.62.tgz#bc93ede0981ee69fe17d753e1d693ce3afa6c16b" + integrity sha512-J58hWY+/G8vOr4J6ZH9hLg0lMSijZtqIIf4HofZezGog/pVX6sJyBJ40dZ1ploFkDIlWTWvJyqtpesBKS73gkQ== + optionalDependencies: + "@swc/core-darwin-arm64" "1.3.62" + "@swc/core-darwin-x64" "1.3.62" + "@swc/core-linux-arm-gnueabihf" "1.3.62" + "@swc/core-linux-arm64-gnu" "1.3.62" + "@swc/core-linux-arm64-musl" "1.3.62" + "@swc/core-linux-x64-gnu" "1.3.62" + "@swc/core-linux-x64-musl" "1.3.62" + "@swc/core-win32-arm64-msvc" "1.3.62" + "@swc/core-win32-ia32-msvc" "1.3.62" + "@swc/core-win32-x64-msvc" "1.3.62" + +"@types/history@^4.7.11": + version "4.7.11" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" + integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== + +"@types/json-schema@^7.0.9": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + +"@types/prop-types@*": + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/react-dom@^18.0.11": + version "18.2.4" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.4.tgz#13f25bfbf4e404d26f62ac6e406591451acba9e0" + integrity sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw== + dependencies: + "@types/react" "*" + +"@types/react-router-dom@^5.3.3": + version "5.3.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" + integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*": + version "5.1.20" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c" + integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + +"@types/react@*", "@types/react@^18.0.37": + version "18.2.8" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.8.tgz#a77dcffe4e9af148ca4aa8000c51a1e8ed99e2c8" + integrity sha512-lTyWUNrd8ntVkqycEEplasWy2OxNlShj3zqS0LuB1ENUGis5HodmhM7DtCoUGbxj3VW/WsGA0DUhpG6XrM7gPA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.3" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" + integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== + +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + +"@typescript-eslint/eslint-plugin@^5.59.0": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz#2604cfaf2b306e120044f901e20c8ed926debf15" + integrity sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/type-utils" "5.59.9" + "@typescript-eslint/utils" "5.59.9" + debug "^4.3.4" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.59.0": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.9.tgz#a85c47ccdd7e285697463da15200f9a8561dd5fa" + integrity sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ== + dependencies: + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/typescript-estree" "5.59.9" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz#eadce1f2733389cdb58c49770192c0f95470d2f4" + integrity sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ== + dependencies: + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/visitor-keys" "5.59.9" + +"@typescript-eslint/type-utils@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz#53bfaae2e901e6ac637ab0536d1754dfef4dafc2" + integrity sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q== + dependencies: + "@typescript-eslint/typescript-estree" "5.59.9" + "@typescript-eslint/utils" "5.59.9" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.9.tgz#3b4e7ae63718ce1b966e0ae620adc4099a6dcc52" + integrity sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw== + +"@typescript-eslint/typescript-estree@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz#6bfea844e468427b5e72034d33c9fffc9557392b" + integrity sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA== + dependencies: + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/visitor-keys" "5.59.9" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.9.tgz#adee890107b5ffe02cd46fdaa6c2125fb3c6c7c4" + integrity sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/typescript-estree" "5.59.9" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz#9f86ef8e95aca30fb5a705bb7430f95fc58b146d" + integrity sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q== + dependencies: + "@typescript-eslint/types" "5.59.9" + eslint-visitor-keys "^3.3.0" + +"@vitejs/plugin-react-swc@^3.0.0": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.3.2.tgz#34a82c1728066f48a86dfecb2f15df60f89207fb" + integrity sha512-VJFWY5sfoZerQRvJrh518h3AcQt6f/yTuWn4/TRB+dqmYU0NX1qz7qM5Wfd+gOQqUzQW4gxKqKN3KpE/P3+zrA== + dependencies: + "@swc/core" "^1.3.61" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.8.0: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +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-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +autoprefixer@^10.4.14: + version "10.4.14" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" + integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== + dependencies: + browserslist "^4.21.5" + caniuse-lite "^1.0.30001464" + fraction.js "^4.2.0" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + +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== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2, 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" + +browserslist@^4.21.5: + version "4.21.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.7.tgz#e2b420947e5fb0a58e8f4668ae6e23488127e551" + integrity sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA== + dependencies: + caniuse-lite "^1.0.30001489" + electron-to-chromium "^1.4.411" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001489: + version "1.0.30001495" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz#64a0ccef1911a9dcff647115b4430f8eff1ef2d9" + integrity sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^3.0.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +electron-to-chromium@^1.4.411: + version "1.4.421" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.421.tgz#2b8c0ef98ba00d4aef4c664933d570922da52161" + integrity sha512-wZOyn3s/aQOtLGAwXMZfteQPN68kgls2wDAnYOA8kCjBvKVrW5RwmWVspxJYTqrcN7Y263XJVsC66VCIGzDO3g== + +esbuild@^0.17.5: + version "0.17.19" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" + integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== + optionalDependencies: + "@esbuild/android-arm" "0.17.19" + "@esbuild/android-arm64" "0.17.19" + "@esbuild/android-x64" "0.17.19" + "@esbuild/darwin-arm64" "0.17.19" + "@esbuild/darwin-x64" "0.17.19" + "@esbuild/freebsd-arm64" "0.17.19" + "@esbuild/freebsd-x64" "0.17.19" + "@esbuild/linux-arm" "0.17.19" + "@esbuild/linux-arm64" "0.17.19" + "@esbuild/linux-ia32" "0.17.19" + "@esbuild/linux-loong64" "0.17.19" + "@esbuild/linux-mips64el" "0.17.19" + "@esbuild/linux-ppc64" "0.17.19" + "@esbuild/linux-riscv64" "0.17.19" + "@esbuild/linux-s390x" "0.17.19" + "@esbuild/linux-x64" "0.17.19" + "@esbuild/netbsd-x64" "0.17.19" + "@esbuild/openbsd-x64" "0.17.19" + "@esbuild/sunos-x64" "0.17.19" + "@esbuild/win32-arm64" "0.17.19" + "@esbuild/win32-ia32" "0.17.19" + "@esbuild/win32-x64" "0.17.19" + +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== + +eslint-plugin-react-hooks@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + +eslint-plugin-react-refresh@^0.3.4: + version "0.3.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.3.5.tgz#0121e3f05f940250d3544bfaeff52e1c6adf4117" + integrity sha512-61qNIsc7fo9Pp/mju0J83kzvLm0Bsayu7OQSLEoJxLDCBjIIyb87bkzufoOvdDxLkSlMfkF7UxomC4+eztUBSA== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@^8.38.0: + version "8.42.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.42.0.tgz#7bebdc3a55f9ed7167251fe7259f75219cade291" + integrity sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.42.0" + "@humanwhocodes/config-array" "^0.11.10" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.12, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +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-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + 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" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + 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-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + 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" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +hamt_plus@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz#e21c252968c7e33b20f6a1b094cd85787a265601" + integrity sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + 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== + +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-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + 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-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jiti@^1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" + integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +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" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lilconfig@^2.0.5, lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +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" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +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== + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-releases@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" + integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== + +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== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +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" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +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 sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" + integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd" + integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA== + dependencies: + lilconfig "^2.0.5" + yaml "^2.1.1" + +postcss-nested@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" + integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== + dependencies: + postcss-selector-parser "^6.0.11" + +postcss-selector-parser@^6.0.11: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.23, postcss@^8.4.24: + version "8.4.24" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df" + integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react-router-dom@^6.12.0: + version "6.12.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.12.0.tgz#372279caaaa1ffb0204926c83e93a139b112d861" + integrity sha512-UzLwZ3ZVaDr6YV0HdjwxuwtDKgwpJx9o1ea9fU0HV4tTvzdB8WPHzlLFMo5orchpIS84e8G4Erlhu7Rl84XDFQ== + dependencies: + "@remix-run/router" "1.6.3" + react-router "6.12.0" + +react-router@6.12.0: + version "6.12.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.12.0.tgz#1afae9219c24c8611809469d7a386c8023ade39a" + integrity sha512-/tCGtLq9umxRvbYeIx3j94CmpQfue0E3qnetVm9luKhu58cR4t+3O4ZrQXBdXfJrBATOAj+wF/1ihJJQI8AoTw== + dependencies: + "@remix-run/router" "1.6.3" + +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +recoil@^0.7.7: + version "0.7.7" + resolved "https://registry.yarnpkg.com/recoil/-/recoil-0.7.7.tgz#c5f2c843224384c9c09e4a62c060fb4c1454dc8e" + integrity sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ== + dependencies: + hamt_plus "1.0.2" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.1.7, resolve@^1.22.2: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup@^3.21.0: + version "3.23.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.23.1.tgz#a6e50cb86a17fc2e3248d8ec12ff8666992b0780" + integrity sha512-ybRdFVHOoljGEFILHLd2g/qateqUdjE6YS41WXq4p3C/WwD3xtWxV4FYWETA1u9TeXQc5K8L8zHE5d/scOvrOQ== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +semver@^7.3.7: + version "7.5.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec" + integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw== + dependencies: + lru-cache "^6.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.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== + +sucrase@^3.32.0: + version "3.32.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.32.0.tgz#c4a95e0f1e18b6847127258a75cf360bc568d4a7" + integrity sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "7.1.6" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tailwindcss@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.2.tgz#2f9e35d715fdf0bbf674d90147a0684d7054a2d3" + integrity sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.2.12" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.18.2" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + postcss-value-parser "^4.2.0" + resolve "^1.22.2" + sucrase "^3.32.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +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" + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typescript@^5.0.2: + version "5.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" + integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== + +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +vite@^4.3.9: + version "4.3.9" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.9.tgz#db896200c0b1aa13b37cdc35c9e99ee2fdd5f96d" + integrity sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg== + dependencies: + esbuild "^0.17.5" + postcss "^8.4.23" + rollup "^3.21.0" + optionalDependencies: + fsevents "~2.3.2" + +which@^2.0.1: + 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" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== + +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== diff --git a/rules-service/Dockerfile b/rules-service/Dockerfile index 01fa3df..c8b93f2 100644 --- a/rules-service/Dockerfile +++ b/rules-service/Dockerfile @@ -4,7 +4,7 @@ EXPOSE 6901 WORKDIR /rules -ADD ./user-service . +ADD ./rules-service/ . COPY ./deno.jsonc . COPY ./secrets.json . COPY ./key.txt . @@ -12,4 +12,4 @@ ADD ./common ./common ADD ./lib ./lib ADD ./middleware ./middleware -CMD ["run", "--allow-net", main.ts, "6901"] +CMD ["run", "--allow-write", "--allow-read", "--allow-net", "--allow-env", "main.ts", "6901"] diff --git a/rules-service/key.txt b/rules-service/key.txt new file mode 100644 index 0000000..ccb5d7e --- /dev/null +++ b/rules-service/key.txt @@ -0,0 +1 @@ +{"kty":"oct","k":"ydUZuTH_gj0WAPHiVAF3ATiHuMoVr85jobnNN_iRHpf-OPQd984g_4hY7zikrmjTXRJARwHv6Rr24E7UoHogvvfGeKF8NkO7yhJ2thF5auv2fyScIMbFMW3tv0AA0YioB0-QUZLBjd1SF9HYK6s5Rqt0-fJaNSKnthzEsKD8wak","alg":"HS512","key_ops":["sign","verify"],"ext":true} \ No newline at end of file diff --git a/rules-service/main.ts b/rules-service/main.ts index a587cd0..8493aae 100644 --- a/rules-service/main.ts +++ b/rules-service/main.ts @@ -4,7 +4,9 @@ import { Router } from 'oak'; const app = new CGGService({ prefix: '/rules' }); -app.route(new Router()); +app.route(new Router() + .get('/', ctx => ctx.response.body = 'rules service') +); app.start(); -console.log('User service running on ' + Deno.args.at(0)); +console.log('rules service running on ' + Deno.args.at(0)); diff --git a/rules-service/perms b/rules-service/perms index 129a934..1d154af 100644 --- a/rules-service/perms +++ b/rules-service/perms @@ -1 +1,4 @@ ---allow-net \ No newline at end of file +--allow-write +--allow-read +--allow-net +--allow-env \ No newline at end of file diff --git a/startDev.ts b/startDev.ts index e844d11..9135cdd 100644 --- a/startDev.ts +++ b/startDev.ts @@ -1,38 +1,38 @@ -import { copy } from "https://deno.land/std@0.104.0/io/util.ts"; import { proxy } from "https://deno.land/x/oak_http_proxy@2.1.0/mod.ts"; import { fileExists } from "./lib/fileExists.ts"; import { Application, Context, Router } from "oak"; +import { path } from "https://deno.land/x/compress@v0.4.1/deps.ts"; const app = new Application(); -let port = 3001; for await (const dirEntry of Deno.readDir(Deno.cwd())) { if (!(dirEntry.isDirectory && dirEntry.name.includes('-service'))) continue; - const filename = dirEntry.name + '/index.ts'; + const filename = dirEntry.name + '/main.ts'; const permfile = dirEntry.name + '/perms'; const prefixfile = dirEntry.name + '/prefix'; + const portfile = dirEntry.name + '/port'; if (!(await fileExists(filename))) continue; if (!(await fileExists(prefixfile))) continue; const perms = (await fileExists(permfile)) ? await Deno.readTextFileSync(permfile).split('\n') : [] // successful, file or directory must exist - const p = Deno.run({ - cmd: ['deno', 'run', ...perms, '--watch', filename, port.toString()], - stdout: "piped", - stderr: "piped", - }) + const port = await Deno.readTextFile(portfile); + const p = new Deno.Command(Deno.execPath(), { + args: [ + 'run', + ...perms, + filename, + port + ] + }).spawn() const prefix = Deno.readTextFileSync(prefixfile); - const fixedPort = port; const routes = new Router() - .all(`/${prefix}/(.*)`, proxy((ctx: Context) => `http://localhost:${fixedPort}${ctx.request.url.pathname}`, {})) - app.use(routes.routes()); + .all(`/${prefix}/(.*)`, proxy((ctx: Context) => `http://localhost:${port}${ctx.request.url.pathname}`, {})) + app.use(routes.allowedMethods()); + app.use(routes.routes()); - port++; - - copy(p.stdout, Deno.stdout); - copy(p.stderr, Deno.stderr); } app.listen({ diff --git a/test.json b/test.json new file mode 100644 index 0000000..8bd16d0 --- /dev/null +++ b/test.json @@ -0,0 +1,8 @@ +{ + "\ufeff\nRIPPER SWARMS\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n2\n6+\n4\n8+\n0\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nSpinemaws [PISTOL]\n6\"\n4\n5+\n3\n0\n1\nCORE: Deep Strike\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse\nXenos claws and teeth [SUSTAINED HITS 1]\nMelee\n6\n5+\n2\n0\n1\nChitinous Horrors (Aura): While an enemy unit is within\nKEYWORDS: Swarm, Great Devourer, Ripper Swarms\n\n\n\n\n\nEngagement Range of this unit, halve the Objective Control\n\n\n\n\n\n\ncharacteristic of models in that enemy unit.\n\n\n\n\n\n\nFACTION KEYWORDS:\n\n\n\n\n\n\nTyranids\n\n\nRIPPER SWARMS\nLiving carpets of Rippers squirm across the ground wherever the \nTyranid swarms advance. Little more than simple eating machines, \nthese chitinous horrors swarm over the wounded and dead alike, and \ncan even drag down trained warriors in sufficient numbers. Once a \nRipper\u2019s fangs sink home, it will not let go\u2026\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 All models in this unit can each be equipped with 1 spinemaws.\t\u25a0 3-6 Ripper Swarms\nEvery model is equipped with: xenos claws and teeth.\nKEYWORDS: Swarm, Great Devourer, Ripper Swarms \tFACTION KEYWORDS: \tTyranids\n\nSCREAMER-KILLER\nM\nT\nSV\nW\nLD\nOC\nBS\nS\nAP\nD\nABILITIES\n8\"\n9\n2+\n10\n8+\n3\n\n\n\n\n\nRANGED WEAPONS\nRANGE\nA\n\n\n\n\n\nBio-plasmic scream [ASSAULT, BLAST]\n18\"\nD6+3\n4+\n8\n-2\n1\nCORE: Deadly Demise 1\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse\nScreamer-killer talons\nMelee\n10\n3+\n10\n-2\n3\nDeath Scream: In your Shooting phase, after this model has\nKEYWORDS: Monster, Great Devourer, Screamer-Killer\n\n\n\n\nshot, select one unit hit by one or more of those attacks.\n\n\n\n\n\nThat unit must take a Battle-shock test, subtracting 1 from\n\n\n\n\n\nthat test.\n\n\n\n\n\nFACTION KEYWORDS:\n\n\n\n\n\nTyranids\n\n\nSCREAMER-KILLER\nAn older adaptation of the basic Carnifex strain, the Screamer-Killer \nwas christened by terrified Imperial troops for the distinctive howl \nit emits as it generates then unleashes its bio-plasmic blasts. \nScreamer-Killers are often seen at the forefront of a Tyranid assault, \nwhere they can inflict the most damage quickly.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Screamer-Killer\nThis model is equipped with: bio-plasmic scream": null, + " \nScreamer-Killer talons.\nKEYWORDS: Monster, Great Devourer, Screamer-Killer\nFACTION KEYWORDS: \nTyranids\n\nPSYCHOPHAGE\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n8\"\n9\n3+\n10\n8+\n3\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nPsychoclastic torrent [IGNORES COVER, TORRENT]\n12\"\nD6\nN/A\n6\n-1\n1\nCORE: Deadly Demise 1, Feel No Pain 5+\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse\nTalons and betentacled maw\nMelee\nD6+1\n3+\n6\n-1\n2\nBio-stimulus (Aura): While a friendly Tyranids unit\n[ANTI-PSYKER 2+, DEVASTATING WOUNDS]\n\n\n\n\n\n\nis within 6\" of this model, models in that unit have the\n\n\n\n\n\n\n\nFeel No Pain 6+ ability.\nFeeding Frenzy: Each time this model makes a melee attack \nthat targets a unit that is below its Starting Strength, add 1 to \nthe Hit roll. If that target is also Below Half-strength, add 1 to \nthe Wound roll as well.\nKEYWORDS: Monster, Great Devourer, Psychophage \tFACTION KEYWORDS: \tTyranids\n\nPSYCHOPHAGE\nThese monsters stampede into battle with frightening speed. They \ndevour any prey organism in their paths, but especially favour those \nvictims with psychic abilities. How they metabolise such esoteric \npowers is unclear, but doing so allows them to project surges of \npsychocorrosive ash that deflagrate their victims\u2019 minds and souls.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Psychophage\nThis model is equipped with: psychoclastic torrent": null, + " talons \nand betentacled maw.\nKEYWORDS: Monster, Great Devourer, Psychophage \tFACTION KEYWORDS: \tTyranids\n\nBARBGAUNTS\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n4\n4+\n2\n8+\n1\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nBio-cannon [BLAST, HEAVY]\n24\"\nD6\n4+\n5\n0\n1\nFACTION: Synapse\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nDisruption Bombardment: In your Shooting phase, after\n\n\n\n\n\n\n\nthis unit has shot, if an enemy Infantry unit was hit by one\nXenos claws and teeth\nMelee\n1\n4+\n4\n0\n1\n\n\n\n\n\n\n\n\nor more of those attacks made by this unit\u2019s bio-cannons,\nKEYWORDS: Infantry, Great Devourer, Barbgaunts\n\n\n\n\n\nuntil the end of your opponent\u2019s next turn, that enemy unit is\n\n\n\n\n\n\ndisrupted. While a unit is disrupted, subtract 2 from its Move\n\n\n\n\n\n\ncharacteristic, and subtract 2 from Advance and Charge rolls\n\n\n\n\n\n\nmade for it.\n\n\n\n\n\n\nFACTION KEYWORDS:\n\n\n\n\n\n\nTyranids\n\n\nBARBGAUNTS\nBarbgaunts are little more than living weapons, their bodies and \nbio-cannons slaved to the will of a pulsating ganglio-parasite that \npiggybacks them into battle. There, they unleash volleys of chitinous \nbarbs that detonate with the fury of violent muscle-spasms and \ntransfix nearby victims with hails of jagged projectiles.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 5-10 Barbgaunts\nEvery model is equipped with: bio-cannon": null, + " xenos claws \nand teeth.\nKEYWORDS: Infantry, Great Devourer, Barbgaunts \tFACTION KEYWORDS: \tTyranids\n\nTERMAGANTS\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n3\n5+\n1\n8+\n2\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nFleshborer [ASSAULT]\n18\"\n1\n4+\n5\n0\n1\nFACTION: Synapse\nTermagant spinefists [ASSAULT, PISTOL, TWIN-LINKED]\n12\"\n2\n4+\n3\n0\n1\nSkulking Horrors: Once per turn, when an enemy unit ends a\nTermagant devourer\n18\"\n2\n4+\n4\n0\n1\n\n\n\n\n\n\n\n\nNormal, Advance or Fall Back move within 9\" of this unit, if this\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nunit is not within Engagement Range of one or more enemy\n\n\n\n\n\n\n\nunits, it can make a Normal move of up to D6\".\nXenos claws and teeth\nMelee\n1\n4+\n3\n0\n1\n\n\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Termagants\nFACTION KEYWORDS: \nTyranids\n\nTERMAGANTS\nScuttling predators that attack in huge swarms, Termagants were \noriginally spawned to roam the tight arterial passages of hive ships \nand hunt intruders. They harry their prey with a hail of firepower, \nseeking always to outflank and envelop their victims as they erode \ntheir numbers.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 All models in this unit can each have their fleshborer replaced with 1 Termagant devourer.\t\u25a0 10-20 Termagants\n\u25a0 All models in this unit can each have their fleshborer replaced with 1 Termagant spinefists.\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Termagants\nEvery model is equipped with: fleshborer": null, + " xenos claws and teeth.\nFACTION KEYWORDS: \nTyranids\n\nNEUROTYRANT\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n8\n4+\n9\n7+\n3\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nPsychic scream [IGNORES COVER, PSYCHIC, TORRENT]\n18\"\n2D6\nN/A\n5\n-1\n2\nCORE: Leader\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse, Shadow in the Warp\nNeurotyrant claws and lashes\nMelee\n6\n3+\n5\n0\n1\nNode Lash (Psychic): While this model is leading a unit, each\n\n\n\n\n\n\n\ntime a model in that unit makes an attack, add 1 to the Hit roll.\n\n\n\n\n\n\n\nIf the target is Battle-shocked, add 1 to the Wound roll as well.\nPsychic Terror (Psychic): If one or more Neurotyrants \nfrom your army are on the battlefield when you unleash the \nShadow in the Warp, subtract 1 from the Battle-shock test \neach enemy unit on the battlefield must take as a result.\nSynaptic Relays: In your Command phase, you can select \nup to two friendly Tyranids units within 12\" of this model\u2019s \nunit. Until the start of your next Command phase, the selected \nunits are always considered to be within Synapse Range of \nyour army.\nDesigner\u2019s Note: Place a Synaptic Relay token next to each selected unit to \nremind you. \nINVULNERABLE SAVE \t4+\nKEYWORDS: Monster, Character, Fly, Psyker, Great Devourer, Synapse, \tNeurotyrant\nFACTION KEYWORDS: \nTyranids\n\nNEUROTYRANT\nThe Shadow in the Warp radiating from this immensely powerful \npsyker-analogue creeps in all directions, driving even non-psychic \nprey organisms to screaming madness. As its foes writhe in agony, \nthe Neurotyrant guides the swarms around it to slaughter with \nbrutal efficiency.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Neurotyrant\nThis model is equipped with: psychic scream": null, + " Neurotyrant \nclaws and lashes.\nLEADER\nThis model can be attached to the following units:\n\u25a0 Neurogaunts\n\u25a0 Tyrant Guard\nKEYWORDS: Monster, Character, Fly, Psyker, Great Devourer, Synapse, \tNeurotyrant\nFACTION KEYWORDS: \nTyranids\n\nVON RYAN\u2019S LEAPERS\nM\nT\nSV\nW\nLD\nOC\nA\nWS\nS\nAP\nD\nABILITIES\n10\"\n5\n4+\n3\n8+\n1\n\n\n\n\n\n\nMELEE WEAPONS\n\n\nRANGE\n\n\n\n\n\n\nLeaper\u2019s talons\n\n\nMelee\n6\n3+\n5\n-1\n1\nCORE: Fights First, Infiltrators, Stealth\nFACTION: Synapse\nPouncing Leap: You can target this unit with the Heroic \nIntervention Stratagem for 0CP, and can do so even if \nyou have already used that Stratagem on a different unit \nthis phase.\nKEYWORDS: Infantry, Great Devourer, Von Ryan\u2019s Leapers\nINVULNERABLE SAVE\n6+\n\nFACTION KEYWORDS:\n\n\nTyranids\n\n\n\nVON RYAN\u2019S LEAPERS\nStealthy hunters and expert ambushers, Von Ryan\u2019s Leapers are swift, \nagile and especially lethal when fighting in dense terrain. Akin to \nliving mines, they lie still at the optimum locations to cause as much \ndamage as possible. When they sense the perfect time to strike, they \nbutcher all around in a murderous frenzy.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 3-6 Von Ryan\u2019s Leapers\nEvery model is equipped with: Leaper\u2019s talons.\nKEYWORDS: Infantry, Great Devourer, Von Ryan\u2019s Leapers\nFACTION KEYWORDS: \nTyranids\n\nNEUROGAUNTS\nM\nT\nSV\nW\nLD\nOC\nA\nWS\nS\nAP\nD\nABILITIES\n6\"\n3\n6+\n1\n8+\n1\n\n\n\n\n\n\nMELEE WEAPONS\n\n\nRANGE\n\n\n\n\n\n\nXenos claws and teeth\n\n\nMelee\n1\n4+\n3\n0\n1\nFACTION: Synapse\nNeurocytes: While this unit is within Synapse Range of your \narmy, it has the Synapse keyword.\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Neurogaunts\nFACTION KEYWORDS: \nTyranids\n\nNEUROGAUNTS\nNeurogaunts scuttle forward in seething masses, driven on by the \nparasitic neurocytes that cling to their backs. Their primary purpose is \nto protect the synaptic node beasts coordinating invasion swarms. It \nis a task they go about with single-minded savagery, slashing, biting \nand giving their lives without an instant\u2019s hesitation.\nWARGEAR OPTIONS\n\u25a0 None\nUNIT COMPOSITION\n\u25a0 1-2 Neurogaunt Nodebeasts*\n\u25a0 10-20 Neurogaunts\nEvery model is equipped with: xenos claws and teeth.\n* This unit can only contain 2 Neurogaunt Nodebeasts if it contains \n20 Neurogaunts.\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Neurogaunts\nFACTION KEYWORDS: \nTyranids\n\nWINGED TYRANID PRIME\nM\nT\nSV\nW\nLD\nOC\nA\nWS\nS\nAP\nD\nABILITIES\n12\"\n5\n4+\n6\n7+\n1\n\n\n\n\n\n\nMELEE WEAPONS\n\n\nRANGE\n\n\n\n\n\n\nPrime talons\n\n\nMelee\n6\n2+\n6\n-1\n2\nCORE: Deep Strike, Leader\nFACTION: Shadow in the Warp, Synapse\nAlpha Warrior: While this model is leading a unit, \nweapons equipped by models in that unit have the \n[SUSTAINED HITS 1] ability.\nDeath Blow: If this model is destroyed by a melee attack, if it \nhas not fought this phase, roll one D6: on a 4+, do not remove \nit from play. The destroyed model can fight after the attacking \nmodel\u2019s unit has finished making its attacks, and is then \nremoved from play.\nKEYWORDS: Infantry, Character, Fly, Great Devourer, Synapse, \tWinged Tyranid Prime\nFACTION KEYWORDS: \nTyranids\n\n\nWINGED TYRANID PRIME\nTyranid Primes adapted for flight possess all the physical and synaptic \nmight of an alpha war-beast, while also boasting the frightening speed \nand manoeuvrability imparted by huge leathery wings. Swooping \ndown into the midst of the foe, they rend and tear until nought remains \nbut corpses and fleeing prey.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Winged Tyranid Prime\nThis model is equipped with: Prime talons.\nLEADER\nThis model can be attached to the following units:\n\u25a0 Gargoyles\n\u25a0 Tyranid Warriors with melee Bio-weapons\n\u25a0 Tyranid Warriors with Ranged Bio-weapons\nKEYWORDS: Infantry, Character, Fly, Great Devourer, Synapse, \tWinged Tyranid Prime\nFACTION KEYWORDS: \nTyranids": null +} \ No newline at end of file diff --git a/user-service/Dockerfile b/user-service/Dockerfile index b2b27c2..8dfcc27 100644 --- a/user-service/Dockerfile +++ b/user-service/Dockerfile @@ -4,7 +4,7 @@ EXPOSE 6900 WORKDIR /user -ADD ./user-service . +ADD ./user-service/ . COPY ./deno.jsonc . COPY ./secrets.json . COPY ./key.txt . @@ -12,4 +12,4 @@ ADD ./common ./common ADD ./lib ./lib ADD ./middleware ./middleware -CMD ["run", "--allow-read", "--allow-write", "--allow-net", "--allow-sys", "--allow-env", main.ts, "6900"] +CMD ["run", "--allow-read", "--allow-write", "--allow-net", "--allow-sys", "--allow-env", "main.ts", "6900"] diff --git a/user-service/key.txt b/user-service/key.txt new file mode 100644 index 0000000..083d2ba --- /dev/null +++ b/user-service/key.txt @@ -0,0 +1 @@ +{"kty":"oct","k":"7t_uWZkFrXoHs2QT9KwIPPqeoZ4YBVLIMg_YbiubAFyhiSCMjZ_k6gEeQHHjdXa2E02dB5SrpWaYN4FtwWyEPYfRcdO19eCN3nDM1dcLQZ9aaOMC-6DFBN7g9LKkm6sEFf48kyvOB_Kmm0m7XWAIhd0rdq_lv5KKtzdaBaxyd6g","alg":"HS512","key_ops":["sign","verify"],"ext":true} \ No newline at end of file diff --git a/user-service/main.ts b/user-service/main.ts index fa440d1..cd83aae 100644 --- a/user-service/main.ts +++ b/user-service/main.ts @@ -46,4 +46,4 @@ app.route(new Router() // app.use(routes.allowedMethods()); app.start(); -console.log('User service running on ' + Deno.args.at(0)); +console.log('user service running on ' + Deno.args.at(0));