diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..7400ce3 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,45 @@ +name: Tests + +on: + pull_request: + branches: + - main + - dev + workflow_dispatch: + +env: + EM_CACHE_FOLDER: "emsdk-cache" + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: "Setup pnpm" + uses: pnpm/action-setup@v4 + with: + run_install: false + + - name: "Setup node" + uses: actions/setup-node@v2 + with: + node-version: "23.6.0" + cache: "pnpm" + + - name: "Install dependencies" + run: pnpm install + + - name: "Install emscipten" + uses: "mymindstorm/setup-emsdk@v14" + with: + actions-cache-folder: ${{env.EM_CACHE_FOLDER}} + + - name: "Run tests" + run: pnpm test:unit + + - name: "Run linter" + run: pnpm clean && pnpm lint diff --git a/.husky/pre-commit b/.husky/pre-commit index b2876f3..925a2c4 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1,3 @@ -bun lint-staged -bun nx run-many --target=lint +pnpm lint-staged +pnpm fix +pnpm lint diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..71e9c16 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1 @@ +/debug/ \ No newline at end of file diff --git a/example/pong/.gitignore b/example/pong/.gitignore new file mode 100644 index 0000000..6162e42 --- /dev/null +++ b/example/pong/.gitignore @@ -0,0 +1,225 @@ +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + diff --git a/example/pong/.idea/.gitignore b/example/pong/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/example/pong/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/example/pong/.idea/codeStyles/Project.xml b/example/pong/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..f506715 --- /dev/null +++ b/example/pong/.idea/codeStyles/Project.xml @@ -0,0 +1,111 @@ + + + + \ No newline at end of file diff --git a/example/pong/.idea/codeStyles/codeStyleConfig.xml b/example/pong/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/example/pong/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/example/pong/.idea/editor.xml b/example/pong/.idea/editor.xml new file mode 100644 index 0000000..b4052db --- /dev/null +++ b/example/pong/.idea/editor.xml @@ -0,0 +1,43 @@ + + + + + \ No newline at end of file diff --git a/example/pong/.idea/inspectionProfiles/Project_Default.xml b/example/pong/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..22cdf9b --- /dev/null +++ b/example/pong/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/example/pong/.idea/modules.xml b/example/pong/.idea/modules.xml new file mode 100644 index 0000000..c81b3d6 --- /dev/null +++ b/example/pong/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/example/pong/.idea/pong.iml b/example/pong/.idea/pong.iml new file mode 100644 index 0000000..bc2cd87 --- /dev/null +++ b/example/pong/.idea/pong.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/example/pong/.idea/prettier.xml b/example/pong/.idea/prettier.xml new file mode 100644 index 0000000..b0c1c68 --- /dev/null +++ b/example/pong/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/example/pong/.idea/vcs.xml b/example/pong/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/example/pong/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/example/pong/.nvmrc b/example/pong/.nvmrc new file mode 100644 index 0000000..c9758a5 --- /dev/null +++ b/example/pong/.nvmrc @@ -0,0 +1 @@ +v23.6.0 diff --git a/example/pong/.prettierignore b/example/pong/.prettierignore new file mode 100644 index 0000000..e77da01 --- /dev/null +++ b/example/pong/.prettierignore @@ -0,0 +1,5 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lock diff --git a/example/pong/.prettierrc b/example/pong/.prettierrc new file mode 100644 index 0000000..d5f635c --- /dev/null +++ b/example/pong/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderParserPlugins": ["typescript", "decorators-legacy"], + "importOrder": ["^~/(.*)$", "^[./]"], + "useTabs": false, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/example/pong/README.md b/example/pong/README.md new file mode 100644 index 0000000..abd9ad3 --- /dev/null +++ b/example/pong/README.md @@ -0,0 +1,31 @@ +## setup.sh + +Allow you init your game + +```shell +./setup.sh +``` + +## update.sh + +Allow you to update your lib + +```shell +./update.sh +``` + +## build.sh + +Allow you to build project and copy it to the loader + +```shell +./build.sh Loader +``` + +## run.sh + +Allow you to build project and copy it to the loader, and then run the loader (Ctrl + C to stop it) + +```shell +./run.sh Loader +``` \ No newline at end of file diff --git a/example/pong/build.sh b/example/pong/build.sh new file mode 100755 index 0000000..b886e83 --- /dev/null +++ b/example/pong/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +bun run build +mkdir -p ../../../${1}/apps/server/public/game +cp dist/* ../../../${1}/apps/server/public/game diff --git a/example/pong/bun.lock b/example/pong/bun.lock new file mode 100644 index 0000000..bb7f152 --- /dev/null +++ b/example/pong/bun.lock @@ -0,0 +1,345 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "nanoforge-loader-web", + "devDependencies": { + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/bun": "latest", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "prettier": "^3.5.3", + "typescript-eslint": "^8.26.0", + }, + "optionalDependencies": { + "@nanoforge/asset-manager": "latest", + "@nanoforge/common": "latest", + "@nanoforge/core": "latest", + "@nanoforge/ecs": "latest", + "@nanoforge/graphics-2d": "latest", + }, + "peerDependencies": { + "typescript": "^5", + }, + }, + }, + "packages": { + "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@babel/generator": ["@babel/generator@7.26.9", "", { "dependencies": { "@babel/parser": "^7.26.9", "@babel/types": "^7.26.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@babel/parser": ["@babel/parser@7.26.9", "", { "dependencies": { "@babel/types": "^7.26.9" }, "bin": "./bin/babel-parser.js" }, "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A=="], + + "@babel/template": ["@babel/template@7.26.9", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.26.9", "@babel/types": "^7.26.9" } }, "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA=="], + + "@babel/traverse": ["@babel/traverse@7.26.9", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.9", "@babel/parser": "^7.26.9", "@babel/template": "^7.26.9", "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg=="], + + "@babel/types": ["@babel/types@7.26.9", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw=="], + + "@dprint/formatter": ["@dprint/formatter@0.3.0", "", {}, "sha512-N9fxCxbaBOrDkteSOzaCqwWjso5iAe+WJPsHC021JfHNj2ThInPNEF13ORDKta3llq5D1TlclODCvOvipH7bWQ=="], + + "@dprint/markdown": ["@dprint/markdown@0.17.8", "", {}, "sha512-ukHFOg+RpG284aPdIg7iPrCYmMs3Dqy43S1ejybnwlJoFiW02b+6Bbr5cfZKFRYNP3dKGM86BqHEnMzBOyLvvA=="], + + "@dprint/toml": ["@dprint/toml@0.6.4", "", {}, "sha512-bZXIUjxr0LIuHWshZr/5mtUkOrnh0NKVZEF6ACojW5z7zkJu7s9sV2mMXm8XQDqN4cJzdHYUYzUyEGdfciaLJA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.19.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.1.0", "", {}, "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA=="], + + "@eslint/core": ["@eslint/core@0.12.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.0", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.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" } }, "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ=="], + + "@eslint/js": ["@eslint/js@9.22.0", "", {}, "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.7", "", { "dependencies": { "@eslint/core": "^0.12.0", "levn": "^0.4.1" } }, "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@pkgr/core": ["@pkgr/core@0.1.1", "", {}, "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA=="], + + "@trivago/prettier-plugin-sort-imports": ["@trivago/prettier-plugin-sort-imports@5.2.2", "", { "dependencies": { "@babel/generator": "^7.26.5", "@babel/parser": "^7.26.7", "@babel/traverse": "^7.26.7", "@babel/types": "^7.26.7", "javascript-natural-sort": "^0.7.1", "lodash": "^4.17.21" }, "peerDependencies": { "@vue/compiler-sfc": "3.x", "prettier": "2.x - 3.x", "prettier-plugin-svelte": "3.x", "svelte": "4.x || 5.x" }, "optionalPeers": ["@vue/compiler-sfc", "prettier-plugin-svelte", "svelte"] }, "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA=="], + + "@types/bun": ["@types/bun@1.2.4", "", { "dependencies": { "bun-types": "1.2.4" } }, "sha512-QtuV5OMR8/rdKJs213iwXDpfVvnskPXY/S0ZiFbsTjQZycuqPbMW8Gf/XhLfwE5njW8sxI2WjISURXPlHypMFA=="], + + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], + + "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.26.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/type-utils": "8.26.1", "@typescript-eslint/utils": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.26.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1" } }, "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.26.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/utils": "8.26.1", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.26.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg=="], + + "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "bun-types": ["bun-types@1.2.4", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-nDPymR207ZZEoWD4AavvEaa/KZe/qlrbMSchqpQwovPZCKc7pwMoENjEtHgMKaAjJhy+x6vfqSBA1QU3bJgs0Q=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.22.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", "@eslint/config-helpers": "^0.1.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", "@eslint/js": "9.22.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.1", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw=="], + + "eslint-formatting-reporter": ["eslint-formatting-reporter@0.0.0", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "sha512-k9RdyTqxqN/wNYVaTk/ds5B5rA8lgoAmvceYN7bcZMBwU7TuXx5ntewJv81eF3pIL/CiJE+pJZm36llG8yhyyw=="], + + "eslint-parser-plain": ["eslint-parser-plain@0.1.1", "", {}, "sha512-KRgd6wuxH4U8kczqPp+Oyk4irThIhHWxgFgLDtpgjUGVIS3wGrJntvZW/p6hHq1T4FOwnOtCNkvAI4Kr+mQ/Hw=="], + + "eslint-plugin-format": ["eslint-plugin-format@1.0.1", "", { "dependencies": { "@dprint/formatter": "^0.3.0", "@dprint/markdown": "^0.17.8", "@dprint/toml": "^0.6.4", "eslint-formatting-reporter": "^0.0.0", "eslint-parser-plain": "^0.1.1", "prettier": "^3.4.2", "synckit": "^0.9.2" }, "peerDependencies": { "eslint": "^8.40.0 || ^9.0.0" } }, "sha512-Tdns+CDjS+m7QrM85wwRi2yLae88XiWVdIOXjp9mDII0pmTBQlczPCmjpKnjiUIY3yPZNLqb5Ms/A/JXcBF2Dw=="], + + "eslint-plugin-prettier": ["eslint-plugin-prettier@5.2.3", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw=="], + + "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], + + "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "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.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@16.0.0", "", {}, "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "javascript-natural-sort": ["javascript-natural-sort@0.7.1", "", {}, "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "optionator": ["optionator@0.9.4", "", { "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.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], + + "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "synckit": ["synckit@0.9.2", "", { "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" } }, "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "ts-api-utils": ["ts-api-utils@2.0.1", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], + + "typescript-eslint": ["typescript-eslint@8.26.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.26.1", "@typescript-eslint/parser": "8.26.1", "@typescript-eslint/utils": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + } +} diff --git a/example/pong/eslint.config.js b/example/pong/eslint.config.js new file mode 100644 index 0000000..efc80f1 --- /dev/null +++ b/example/pong/eslint.config.js @@ -0,0 +1,44 @@ +import pluginJs from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default [ + { files: ["src/**/*.{js,mjs,cjs,ts}"] }, + { languageOptions: { globals: globals.node } }, + + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.strict, + eslintConfigPrettier, + { + rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + disallowTypeAnnotations: true, + fixStyle: "inline-type-imports", + prefer: "type-imports", + }, + ], + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/member-ordering": [ + "error", + { + default: [ + "static-field", + "field", + "public-static-method", + "constructor", + "method", + "protected-method", + "private-method", + ], + }, + ], + }, + }, +]; diff --git a/example/pong/package.json b/example/pong/package.json new file mode 100644 index 0000000..f7a4d20 --- /dev/null +++ b/example/pong/package.json @@ -0,0 +1,69 @@ +{ + "name": "nanoforge-example-template", + "version": "1.0.0", + "description": "NanoForge Loader - Web", + "homepage": "https://github.com/NanoForge-dev/Loader#readme", + "license": "MIT", + "contributors": [ + "Bill", + "Exelo", + "Fexkoser", + "Tchips" + ], + "funding": { + "type": "individual", + "url": "" + }, + "type": "module", + "module": "src/index.ts", + "browser": true, + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Loader.git", + "directory": "apps/web" + }, + "private": true, + "scripts": { + "setup": "bun i", + "build": "bun run clean && bun run build:raw", + "build:raw": "bun build src/index.ts --outdir dist --asset-naming \"[name].[ext]\"", + "clean": "rm -rf dist", + "lint": "eslint . && prettier --check . '!.cloud/**'", + "fix": "eslint . --fix && prettier --write . '!.cloud/**'", + "taze": "taze major -w", + "lint-staged": "lint-staged" + }, + "devDependencies": { + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/bun": "latest", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "prettier": "^3.5.3", + "typescript-eslint": "^8.26.0" + }, + "peerDependencies": { + "typescript": "^5" + }, + "optionalDependencies": { + "@nanoforge/common": "latest", + "@nanoforge/core": "latest", + "@nanoforge/asset-manager": "latest", + "@nanoforge/ecs": "latest", + "@nanoforge/graphics-2d": "latest" + }, + "engines": { + "node": "23.6.0", + "bun": "1.2.4" + }, + "packageManager": "bun@1.2.4", + "lint-staged": { + "**/*.{js,ts,html,css}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/example/pong/run.sh b/example/pong/run.sh new file mode 100755 index 0000000..73745c1 --- /dev/null +++ b/example/pong/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +./build.sh ${1} +cd ../../../${1}/apps + +bun run dev diff --git a/example/pong/setup.sh b/example/pong/setup.sh new file mode 100755 index 0000000..2ec3371 --- /dev/null +++ b/example/pong/setup.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +bun i --omit=optional +./update.sh diff --git a/example/pong/src/collisions.ts b/example/pong/src/collisions.ts new file mode 100644 index 0000000..224b59a --- /dev/null +++ b/example/pong/src/collisions.ts @@ -0,0 +1,28 @@ +import { Hitbox, Position } from "./components"; +import { ecsLibrary } from "./index"; + +export function checkCollisions(entity: any) { + const entities = ecsLibrary.getZipper([Hitbox, Position]); + + const { x, y } = entity.Position; + const { width, height } = entity.Hitbox; + + for (const e of entities) { + if (e === undefined) continue; + const { x: ex, y: ey } = e.Position; + const { width: ew, height: eh } = e.Hitbox; + + if ( + e.Position != entity.Position && + e.Hitbox != entity.Hitbox && + x < ex + ew && + x + width > ex && + y < ey + eh && + y + height > ey + ) { + return true; + } + } + + return false; +} diff --git a/example/pong/src/components.ts b/example/pong/src/components.ts new file mode 100644 index 0000000..05f58ae --- /dev/null +++ b/example/pong/src/components.ts @@ -0,0 +1,69 @@ +import type { NfgCircle } from "@nanoforge/graphics-2d"; +import type { NfgRectangle } from "@nanoforge/graphics-2d/src/components/shape/shapes/rectangle.shape"; +import type { InputEnum } from "@nanoforge/input"; + +export class Velocity { + name = "Velocity"; + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +export class Position { + name = "Position"; + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +export class Hitbox { + name = "Hitbox"; + height: number; + width: number; + + constructor(width: number, height: number) { + this.height = height; + this.width = width; + } +} + +export class CircleComponent { + name = "CircleComponent"; + component: NfgCircle; + + constructor(component: NfgCircle) { + this.component = component; + } +} + +export class RectangleComponent { + name = "RectangleComponent"; + component: NfgRectangle; + + constructor(component: NfgRectangle) { + this.component = component; + } +} + +export class Bounce { + name = "Bounce"; +} + +export class Controller { + name = "Controller"; + up: InputEnum; + down: InputEnum; + + constructor(up: InputEnum, down: InputEnum) { + this.up = up; + this.down = down; + } +} diff --git a/example/pong/src/index.ts b/example/pong/src/index.ts new file mode 100644 index 0000000..e853ee5 --- /dev/null +++ b/example/pong/src/index.ts @@ -0,0 +1,120 @@ +import { AssetManagerLibrary } from "@nanoforge/asset-manager"; +import { type IRunOptions } from "@nanoforge/common"; +import { NanoforgeFactory } from "@nanoforge/core"; +import { ECSLibrary } from "@nanoforge/ecs"; +import { Graphics2DLibrary } from "@nanoforge/graphics-2d"; +import { InputLibrary } from "@nanoforge/input"; +import { InputEnum } from "@nanoforge/input"; + +import { + Bounce, + CircleComponent, + Controller, + Hitbox, + Position, + RectangleComponent, + Velocity, +} from "./components"; +import { bounce, controlPlayer, drawCircle, drawRectangle, move, moveRectangle } from "./systems"; + +export const ecsLibrary = new ECSLibrary(); + +export const app = NanoforgeFactory.createClient(); +export const graphics = new Graphics2DLibrary(); +export const inputs = new InputLibrary(); + +export const main = async (options: IRunOptions) => { + app.useGraphics(graphics); + app.useComponentSystem(ecsLibrary); + app.useAssetManager(new AssetManagerLibrary()); + app.useInput(inputs); + + await app.init(options); + + const ball = ecsLibrary.createEntity(); + ecsLibrary.addComponent(ball, new Velocity(0.04, 0)); + ecsLibrary.addComponent(ball, new Position(0.5, 0)); + ecsLibrary.addComponent(ball, new Bounce()); + ecsLibrary.addComponent( + ball, + new CircleComponent( + await graphics.factory.createCircle({ + radius: 0.1, + color: { r: 1, g: 0, b: 0, a: 1 }, + }), + ), + ); + + const bg = ecsLibrary.createEntity(); + ecsLibrary.addComponent( + bg, + new RectangleComponent( + await graphics.factory.createRectangle({ + min: { x: -2, y: -1 }, + max: { x: 2, y: 1 }, + color: { r: 0, g: 0, b: 0, a: 0 }, + }), + ), + ); + + const topWall = ecsLibrary.createEntity(); + ecsLibrary.addComponent( + topWall, + new RectangleComponent( + await graphics.factory.createRectangle({ + color: { r: 0, g: 0, b: 0, a: 1 }, + }), + ), + ); + ecsLibrary.addComponent(topWall, new Position(-1.8, 0.91)); + ecsLibrary.addComponent(topWall, new Hitbox(3.6, 0.1)); + + const botWall = ecsLibrary.createEntity(); + ecsLibrary.addComponent( + botWall, + new RectangleComponent( + await graphics.factory.createRectangle({ + color: { r: 0, g: 0, b: 0, a: 1 }, + }), + ), + ); + ecsLibrary.addComponent(botWall, new Position(-1.8, -1)); + ecsLibrary.addComponent(botWall, new Hitbox(3.6, 0.1)); + + const player1 = ecsLibrary.createEntity(); + ecsLibrary.addComponent(player1, new Position(-1.8, -0.3)); + ecsLibrary.addComponent(player1, new Velocity(0, 0.1)); + ecsLibrary.addComponent(player1, new Hitbox(0.1, 0.5)); + ecsLibrary.addComponent(player1, new Controller(InputEnum.KeyW, InputEnum.KeyS)); + ecsLibrary.addComponent( + player1, + new RectangleComponent( + await graphics.factory.createRectangle({ + color: { r: 0, g: 0, b: 1, a: 1 }, + }), + ), + ); + + const player2 = ecsLibrary.createEntity(); + ecsLibrary.addComponent(player2, new Position(1.7, -0.3)); + ecsLibrary.addComponent(player2, new Velocity(0, 0.1)); + ecsLibrary.addComponent(player2, new Hitbox(0.1, 0.5)); + ecsLibrary.addComponent(player2, new Controller(InputEnum.ArrowUp, InputEnum.ArrowDown)); + ecsLibrary.addComponent( + player2, + new RectangleComponent( + await graphics.factory.createRectangle({ + color: { r: 0, g: 0, b: 1, a: 1 }, + }), + ), + ); + + ecsLibrary.addSystem(move); + ecsLibrary.addSystem(controlPlayer); + ecsLibrary.addSystem(moveRectangle); + ecsLibrary.addSystem(drawRectangle); + ecsLibrary.addSystem(drawCircle); + ecsLibrary.addSystem(bounce); + + app.run(); +}; diff --git a/example/pong/src/systems.ts b/example/pong/src/systems.ts new file mode 100644 index 0000000..2a2f6a3 --- /dev/null +++ b/example/pong/src/systems.ts @@ -0,0 +1,81 @@ +import { checkCollisions } from "./collisions"; +import { + Bounce, + CircleComponent, + Controller, + Hitbox, + Position, + RectangleComponent, + Velocity, +} from "./components"; +import { ecsLibrary, graphics, inputs } from "./index"; + +export function move() { + const entities = ecsLibrary.getZipper([Bounce, Position, Velocity]); + + entities.forEach((entity) => { + entity.Position.x += entity.Velocity.x; + entity.Position.y += entity.Velocity.y; + }); +} + +export function bounce() { + const entities = ecsLibrary.getZipper([Bounce, Position, Velocity]); + + entities.forEach((entity) => { + if (entity.Position.x >= 1.6 || entity.Position.x <= -1.6) { + entity.Velocity.x = -entity.Velocity.x; + } + if (entity.Position.y >= 1 || entity.Position.y <= -1) { + entity.Velocity.y = -entity.Velocity.y; + } + }); +} + +export function controlPlayer() { + const entities = ecsLibrary.getZipper([Controller, Position, Hitbox, Velocity]); + + entities.forEach((entity) => { + if (inputs.isKeyPressed(entity.Controller.up) && !checkCollisions(entity)) { + entity.Position.y += entity.Velocity.y; + } else { + entity.Position.y -= entity.Velocity.y; + } + if (inputs.isKeyPressed(entity.Controller.down) && !checkCollisions(entity)) { + entity.Position.y -= entity.Velocity.y; + } else { + entity.Position.y += entity.Velocity.y; + } + }); +} + +export function drawCircle() { + const entities = ecsLibrary.getZipper([CircleComponent, Position]); + + entities.forEach((entity) => { + const pos = entity.Position; + entity.CircleComponent.component.setPosition(pos); + graphics.getWindow().draw(entity.CircleComponent.component); + }); +} + +export function moveRectangle() { + const entities = ecsLibrary.getZipper([RectangleComponent, Position, Hitbox]); + + entities.forEach((entity) => { + const pos = entity.Position; + entity.RectangleComponent.component.setMin({ x: pos.x, y: pos.y }); + entity.RectangleComponent.component.setMax({ + x: pos.x + entity.Hitbox.width, + y: pos.y + entity.Hitbox.height, + }); + }); +} + +export function drawRectangle() { + const entities = ecsLibrary.getZipper([RectangleComponent]); + + entities.forEach((entity) => { + graphics.getWindow().draw(entity.RectangleComponent.component); + }); +} diff --git a/example/pong/tsconfig.json b/example/pong/tsconfig.json new file mode 100644 index 0000000..d84e1b8 --- /dev/null +++ b/example/pong/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2023", + "module": "commonjs", + "rootDir": "./src", + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "paths": { + } + } +} diff --git a/example/pong/update.sh b/example/pong/update.sh new file mode 100755 index 0000000..3852095 --- /dev/null +++ b/example/pong/update.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +cd ../.. +pnpm build +cd - +mkdir -p node_modules/@nanoforge +cp -rf ../../packages/* node_modules/@nanoforge diff --git a/example/template/.gitignore b/example/template/.gitignore new file mode 100644 index 0000000..6162e42 --- /dev/null +++ b/example/template/.gitignore @@ -0,0 +1,225 @@ +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + diff --git a/example/template/.nvmrc b/example/template/.nvmrc new file mode 100644 index 0000000..c9758a5 --- /dev/null +++ b/example/template/.nvmrc @@ -0,0 +1 @@ +v23.6.0 diff --git a/example/template/.prettierignore b/example/template/.prettierignore new file mode 100644 index 0000000..e77da01 --- /dev/null +++ b/example/template/.prettierignore @@ -0,0 +1,5 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lock diff --git a/example/template/.prettierrc b/example/template/.prettierrc new file mode 100644 index 0000000..d5f635c --- /dev/null +++ b/example/template/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderParserPlugins": ["typescript", "decorators-legacy"], + "importOrder": ["^~/(.*)$", "^[./]"], + "useTabs": false, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/example/template/README.md b/example/template/README.md new file mode 100644 index 0000000..abd9ad3 --- /dev/null +++ b/example/template/README.md @@ -0,0 +1,31 @@ +## setup.sh + +Allow you init your game + +```shell +./setup.sh +``` + +## update.sh + +Allow you to update your lib + +```shell +./update.sh +``` + +## build.sh + +Allow you to build project and copy it to the loader + +```shell +./build.sh Loader +``` + +## run.sh + +Allow you to build project and copy it to the loader, and then run the loader (Ctrl + C to stop it) + +```shell +./run.sh Loader +``` \ No newline at end of file diff --git a/example/template/build.sh b/example/template/build.sh new file mode 100755 index 0000000..b886e83 --- /dev/null +++ b/example/template/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +bun run build +mkdir -p ../../../${1}/apps/server/public/game +cp dist/* ../../../${1}/apps/server/public/game diff --git a/example/template/bun.lock b/example/template/bun.lock new file mode 100644 index 0000000..bb7f152 --- /dev/null +++ b/example/template/bun.lock @@ -0,0 +1,345 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "nanoforge-loader-web", + "devDependencies": { + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/bun": "latest", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "prettier": "^3.5.3", + "typescript-eslint": "^8.26.0", + }, + "optionalDependencies": { + "@nanoforge/asset-manager": "latest", + "@nanoforge/common": "latest", + "@nanoforge/core": "latest", + "@nanoforge/ecs": "latest", + "@nanoforge/graphics-2d": "latest", + }, + "peerDependencies": { + "typescript": "^5", + }, + }, + }, + "packages": { + "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@babel/generator": ["@babel/generator@7.26.9", "", { "dependencies": { "@babel/parser": "^7.26.9", "@babel/types": "^7.26.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@babel/parser": ["@babel/parser@7.26.9", "", { "dependencies": { "@babel/types": "^7.26.9" }, "bin": "./bin/babel-parser.js" }, "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A=="], + + "@babel/template": ["@babel/template@7.26.9", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.26.9", "@babel/types": "^7.26.9" } }, "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA=="], + + "@babel/traverse": ["@babel/traverse@7.26.9", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.9", "@babel/parser": "^7.26.9", "@babel/template": "^7.26.9", "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg=="], + + "@babel/types": ["@babel/types@7.26.9", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw=="], + + "@dprint/formatter": ["@dprint/formatter@0.3.0", "", {}, "sha512-N9fxCxbaBOrDkteSOzaCqwWjso5iAe+WJPsHC021JfHNj2ThInPNEF13ORDKta3llq5D1TlclODCvOvipH7bWQ=="], + + "@dprint/markdown": ["@dprint/markdown@0.17.8", "", {}, "sha512-ukHFOg+RpG284aPdIg7iPrCYmMs3Dqy43S1ejybnwlJoFiW02b+6Bbr5cfZKFRYNP3dKGM86BqHEnMzBOyLvvA=="], + + "@dprint/toml": ["@dprint/toml@0.6.4", "", {}, "sha512-bZXIUjxr0LIuHWshZr/5mtUkOrnh0NKVZEF6ACojW5z7zkJu7s9sV2mMXm8XQDqN4cJzdHYUYzUyEGdfciaLJA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.19.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.1.0", "", {}, "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA=="], + + "@eslint/core": ["@eslint/core@0.12.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.0", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.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" } }, "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ=="], + + "@eslint/js": ["@eslint/js@9.22.0", "", {}, "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.7", "", { "dependencies": { "@eslint/core": "^0.12.0", "levn": "^0.4.1" } }, "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@pkgr/core": ["@pkgr/core@0.1.1", "", {}, "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA=="], + + "@trivago/prettier-plugin-sort-imports": ["@trivago/prettier-plugin-sort-imports@5.2.2", "", { "dependencies": { "@babel/generator": "^7.26.5", "@babel/parser": "^7.26.7", "@babel/traverse": "^7.26.7", "@babel/types": "^7.26.7", "javascript-natural-sort": "^0.7.1", "lodash": "^4.17.21" }, "peerDependencies": { "@vue/compiler-sfc": "3.x", "prettier": "2.x - 3.x", "prettier-plugin-svelte": "3.x", "svelte": "4.x || 5.x" }, "optionalPeers": ["@vue/compiler-sfc", "prettier-plugin-svelte", "svelte"] }, "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA=="], + + "@types/bun": ["@types/bun@1.2.4", "", { "dependencies": { "bun-types": "1.2.4" } }, "sha512-QtuV5OMR8/rdKJs213iwXDpfVvnskPXY/S0ZiFbsTjQZycuqPbMW8Gf/XhLfwE5njW8sxI2WjISURXPlHypMFA=="], + + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], + + "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.26.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/type-utils": "8.26.1", "@typescript-eslint/utils": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.26.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1" } }, "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.26.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/utils": "8.26.1", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.26.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg=="], + + "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "bun-types": ["bun-types@1.2.4", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-nDPymR207ZZEoWD4AavvEaa/KZe/qlrbMSchqpQwovPZCKc7pwMoENjEtHgMKaAjJhy+x6vfqSBA1QU3bJgs0Q=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.22.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", "@eslint/config-helpers": "^0.1.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", "@eslint/js": "9.22.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.1", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw=="], + + "eslint-formatting-reporter": ["eslint-formatting-reporter@0.0.0", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "sha512-k9RdyTqxqN/wNYVaTk/ds5B5rA8lgoAmvceYN7bcZMBwU7TuXx5ntewJv81eF3pIL/CiJE+pJZm36llG8yhyyw=="], + + "eslint-parser-plain": ["eslint-parser-plain@0.1.1", "", {}, "sha512-KRgd6wuxH4U8kczqPp+Oyk4irThIhHWxgFgLDtpgjUGVIS3wGrJntvZW/p6hHq1T4FOwnOtCNkvAI4Kr+mQ/Hw=="], + + "eslint-plugin-format": ["eslint-plugin-format@1.0.1", "", { "dependencies": { "@dprint/formatter": "^0.3.0", "@dprint/markdown": "^0.17.8", "@dprint/toml": "^0.6.4", "eslint-formatting-reporter": "^0.0.0", "eslint-parser-plain": "^0.1.1", "prettier": "^3.4.2", "synckit": "^0.9.2" }, "peerDependencies": { "eslint": "^8.40.0 || ^9.0.0" } }, "sha512-Tdns+CDjS+m7QrM85wwRi2yLae88XiWVdIOXjp9mDII0pmTBQlczPCmjpKnjiUIY3yPZNLqb5Ms/A/JXcBF2Dw=="], + + "eslint-plugin-prettier": ["eslint-plugin-prettier@5.2.3", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw=="], + + "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], + + "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "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.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@16.0.0", "", {}, "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "javascript-natural-sort": ["javascript-natural-sort@0.7.1", "", {}, "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "optionator": ["optionator@0.9.4", "", { "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.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], + + "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "synckit": ["synckit@0.9.2", "", { "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" } }, "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "ts-api-utils": ["ts-api-utils@2.0.1", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], + + "typescript-eslint": ["typescript-eslint@8.26.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.26.1", "@typescript-eslint/parser": "8.26.1", "@typescript-eslint/utils": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + } +} diff --git a/example/template/eslint.config.js b/example/template/eslint.config.js new file mode 100644 index 0000000..efc80f1 --- /dev/null +++ b/example/template/eslint.config.js @@ -0,0 +1,44 @@ +import pluginJs from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default [ + { files: ["src/**/*.{js,mjs,cjs,ts}"] }, + { languageOptions: { globals: globals.node } }, + + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.strict, + eslintConfigPrettier, + { + rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + disallowTypeAnnotations: true, + fixStyle: "inline-type-imports", + prefer: "type-imports", + }, + ], + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/member-ordering": [ + "error", + { + default: [ + "static-field", + "field", + "public-static-method", + "constructor", + "method", + "protected-method", + "private-method", + ], + }, + ], + }, + }, +]; diff --git a/example/template/package.json b/example/template/package.json new file mode 100644 index 0000000..f7a4d20 --- /dev/null +++ b/example/template/package.json @@ -0,0 +1,69 @@ +{ + "name": "nanoforge-example-template", + "version": "1.0.0", + "description": "NanoForge Loader - Web", + "homepage": "https://github.com/NanoForge-dev/Loader#readme", + "license": "MIT", + "contributors": [ + "Bill", + "Exelo", + "Fexkoser", + "Tchips" + ], + "funding": { + "type": "individual", + "url": "" + }, + "type": "module", + "module": "src/index.ts", + "browser": true, + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Loader.git", + "directory": "apps/web" + }, + "private": true, + "scripts": { + "setup": "bun i", + "build": "bun run clean && bun run build:raw", + "build:raw": "bun build src/index.ts --outdir dist --asset-naming \"[name].[ext]\"", + "clean": "rm -rf dist", + "lint": "eslint . && prettier --check . '!.cloud/**'", + "fix": "eslint . --fix && prettier --write . '!.cloud/**'", + "taze": "taze major -w", + "lint-staged": "lint-staged" + }, + "devDependencies": { + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/bun": "latest", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "prettier": "^3.5.3", + "typescript-eslint": "^8.26.0" + }, + "peerDependencies": { + "typescript": "^5" + }, + "optionalDependencies": { + "@nanoforge/common": "latest", + "@nanoforge/core": "latest", + "@nanoforge/asset-manager": "latest", + "@nanoforge/ecs": "latest", + "@nanoforge/graphics-2d": "latest" + }, + "engines": { + "node": "23.6.0", + "bun": "1.2.4" + }, + "packageManager": "bun@1.2.4", + "lint-staged": { + "**/*.{js,ts,html,css}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/example/template/run.sh b/example/template/run.sh new file mode 100755 index 0000000..73745c1 --- /dev/null +++ b/example/template/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +./build.sh ${1} +cd ../../../${1}/apps + +bun run dev diff --git a/example/template/setup.sh b/example/template/setup.sh new file mode 100755 index 0000000..2ec3371 --- /dev/null +++ b/example/template/setup.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +bun i --omit=optional +./update.sh diff --git a/example/template/src/index.ts b/example/template/src/index.ts new file mode 100644 index 0000000..104dbfe --- /dev/null +++ b/example/template/src/index.ts @@ -0,0 +1,16 @@ +import { AssetManagerLibrary } from "@nanoforge/asset-manager"; +import { type IRunOptions } from "@nanoforge/common"; +import { NanoforgeFactory } from "@nanoforge/core"; +import { ECSLibrary } from "@nanoforge/ecs"; +import { Graphics2DLibrary } from "@nanoforge/graphics-2d"; + +export const app = NanoforgeFactory.createClient(); + +export const main = async (options: IRunOptions) => { + app.useGraphics(new Graphics2DLibrary()); + app.useAssetManager(new AssetManagerLibrary()); + app.useComponentSystem(new ECSLibrary()); + + await app.init(options); + app.run(); +}; diff --git a/example/template/tsconfig.json b/example/template/tsconfig.json new file mode 100644 index 0000000..d84e1b8 --- /dev/null +++ b/example/template/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2023", + "module": "commonjs", + "rootDir": "./src", + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "paths": { + } + } +} diff --git a/example/template/update.sh b/example/template/update.sh new file mode 100755 index 0000000..49d2cfd --- /dev/null +++ b/example/template/update.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd ../.. +pnpm clean +pnpm build +cd - +mkdir -p node_modules/@nanoforge +cp -rf ../../packages/* node_modules/@nanoforge diff --git a/packages/asset-manager/.gitignore b/packages/asset-manager/.gitignore new file mode 100644 index 0000000..9f6061c --- /dev/null +++ b/packages/asset-manager/.gitignore @@ -0,0 +1,272 @@ +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Private + +# NX +.nx/ + +# Compiled files +src/**/*.js +src/**/*.d.ts + +# pubilc directory +public/ +compile_commands.json +emsdk/ diff --git a/packages/asset-manager/.idea/.gitignore b/packages/asset-manager/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/packages/asset-manager/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/packages/asset-manager/.idea/.name b/packages/asset-manager/.idea/.name new file mode 100644 index 0000000..0104341 --- /dev/null +++ b/packages/asset-manager/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine Asset Manager \ No newline at end of file diff --git a/packages/asset-manager/.idea/[NanoForge] Engine Asset Manager.iml b/packages/asset-manager/.idea/[NanoForge] Engine Asset Manager.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/packages/asset-manager/.idea/[NanoForge] Engine Asset Manager.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/codeStyles/Project.xml b/packages/asset-manager/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a57ead7 --- /dev/null +++ b/packages/asset-manager/.idea/codeStyles/Project.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml b/packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/editor.xml b/packages/asset-manager/.idea/editor.xml new file mode 100644 index 0000000..d9ec4df --- /dev/null +++ b/packages/asset-manager/.idea/editor.xml @@ -0,0 +1,106 @@ + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/git_toolbox_blame.xml b/packages/asset-manager/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/packages/asset-manager/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/git_toolbox_prj.xml b/packages/asset-manager/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/packages/asset-manager/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/inspectionProfiles/Project_Default.xml b/packages/asset-manager/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..41ec19c --- /dev/null +++ b/packages/asset-manager/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/jsLinters/eslint.xml b/packages/asset-manager/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/packages/asset-manager/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/misc.xml b/packages/asset-manager/.idea/misc.xml new file mode 100644 index 0000000..7ecbce5 --- /dev/null +++ b/packages/asset-manager/.idea/misc.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/modules.xml b/packages/asset-manager/.idea/modules.xml new file mode 100644 index 0000000..b320cde --- /dev/null +++ b/packages/asset-manager/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/prettier.xml b/packages/asset-manager/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/packages/asset-manager/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.idea/vcs.xml b/packages/asset-manager/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/packages/asset-manager/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/asset-manager/.nvmrc b/packages/asset-manager/.nvmrc new file mode 100644 index 0000000..c9758a5 --- /dev/null +++ b/packages/asset-manager/.nvmrc @@ -0,0 +1 @@ +v23.6.0 diff --git a/packages/asset-manager/.prettierignore b/packages/asset-manager/.prettierignore new file mode 100644 index 0000000..e814a63 --- /dev/null +++ b/packages/asset-manager/.prettierignore @@ -0,0 +1,8 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lock + +*.js +*.d.ts diff --git a/packages/asset-manager/.prettierrc b/packages/asset-manager/.prettierrc new file mode 100644 index 0000000..d5f635c --- /dev/null +++ b/packages/asset-manager/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderParserPlugins": ["typescript", "decorators-legacy"], + "importOrder": ["^~/(.*)$", "^[./]"], + "useTabs": false, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/packages/asset-manager/README.md b/packages/asset-manager/README.md new file mode 100644 index 0000000..82cb3ec --- /dev/null +++ b/packages/asset-manager/README.md @@ -0,0 +1 @@ +# Engine Asset Manager diff --git a/packages/asset-manager/eslint.config.js b/packages/asset-manager/eslint.config.js new file mode 100644 index 0000000..4a7529e --- /dev/null +++ b/packages/asset-manager/eslint.config.js @@ -0,0 +1,63 @@ +import pluginJs from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginJest from "eslint-plugin-jest"; + +export default [ + { + files: ["src/**/*.{ts}"], + }, + { languageOptions: { globals: globals.node } }, + + + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.strict, + eslintConfigPrettier, + { ignores: ["**/*.js"] }, + { + rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + disallowTypeAnnotations: true, + fixStyle: "inline-type-imports", + prefer: "type-imports", + }, + ], + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/member-ordering": [ + "error", + { + default: [ + "static-field", + "field", + "public-static-method", + "constructor", + "method", + "protected-method", + "private-method", + ], + }, + ], + }, + }, + { + files: ["**/*.spec.ts"], + plugins: { jest: pluginJest }, + languageOptions: { + globals: pluginJest.environments.globals.globals, + }, + rules: { + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + } + } +]; diff --git a/packages/asset-manager/jest.config.json b/packages/asset-manager/jest.config.json new file mode 100644 index 0000000..b75e6b6 --- /dev/null +++ b/packages/asset-manager/jest.config.json @@ -0,0 +1,12 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": "test", + "collectCoverageFrom": ["**/*.(t|j)s"], + "testEnvironment": "node", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "verbose": true, + "testTimeout": 5000 +} diff --git a/packages/asset-manager/package.json b/packages/asset-manager/package.json new file mode 100644 index 0000000..d5082b1 --- /dev/null +++ b/packages/asset-manager/package.json @@ -0,0 +1,68 @@ +{ + "name": "@nanoforge/asset-manager", + "version": "1.0.0", + "description": "NanoForge Engine - Asset Manager", + "homepage": "https://github.com/NanoForge-dev/Engine#readme", + "license": "MIT", + "contributors": [ + "Bill", + "Exelo", + "Fexkoser", + "Tchips" + ], + "funding": { + "type": "individual", + "url": "" + }, + "type": "module", + "main": "src/index.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Engine.git", + "directory": "packages/asset-manager" + }, + "scripts": { + "build": "tsc -b .", + "clean": "pnpm clean:types && pnpm clean:scripts && rm -f tsconfig.build.tsbuildinfo", + "clean:types": "find src -name '*.d.ts' -delete", + "clean:scripts": "find src -name '*.js' -delete", + "lint": "eslint . && prettier --check .", + "fix": "eslint . --fix && prettier --write .", + "taze": "taze major -w", + "lint-staged": "lint-staged", + "test:unit": "jest --config ./jest.config.json" + }, + "dependencies": { + "@nanoforge/common": "workspace:^" + }, + "devDependencies": { + "@commitlint/cli": "^19.8.0", + "@commitlint/config-conventional": "^19.8.0", + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/jest": "^29.5.14", + "@types/node": "^22.13.10", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "jest": "^29.7.0", + "lint-staged": "^15.4.3", + "prettier": "^3.5.3", + "ts-jest": "^29.2.6", + "typescript": "^5.8.2", + "typescript-eslint": "^8.26.0" + }, + "engines": { + "node": "23.6.0", + "pnpm": "10.6.2" + }, + "lint-staged": { + "**/*.{js,ts}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/packages/asset-manager/src/asset-manager.library.ts b/packages/asset-manager/src/asset-manager.library.ts new file mode 100644 index 0000000..81fa345 --- /dev/null +++ b/packages/asset-manager/src/asset-manager.library.ts @@ -0,0 +1,53 @@ +import { BaseAssetManagerLibrary, type InitContext } from "@nanoforge/common"; + +import { NfFile } from "./file"; + +export class AssetManagerLibrary extends BaseAssetManagerLibrary { + private _assets: Map; + private _wasm: Map; + private _wgsl: Map; + + get name(): string { + return "AssetManagerLibrary"; + } + + public async init(context: InitContext): Promise { + this._assets = context.files.assets; + this._wasm = context.files.wasm; + this._wgsl = context.files.wgsl; + } + + /** + * @todo Error management + */ + public async getAsset(path: string): Promise { + const res = this._assets.get(this._parsePath(path)); + if (!res) throw new Error("Asset not found."); + return new NfFile(res); + } + + /** + * @todo Error management + */ + public async getWasm(path: string): Promise { + const res = this._wasm.get(this._parsePath(path)); + if (!res) throw new Error("Asset not found."); + return new NfFile(res); + } + + /** + * @todo Error management + */ + public async getWgsl(path: string): Promise { + const res = this._wgsl.get(this._parsePath(path)); + if (!res) throw new Error("Asset not found."); + return new NfFile(res); + } + + private _parsePath(path: string): string { + return path + .replace(/^(\/*)/, "/") + .replaceAll(/(\/+)/g, "/") + .replace(/(\/+)$/, ""); + } +} diff --git a/packages/asset-manager/src/file.ts b/packages/asset-manager/src/file.ts new file mode 100644 index 0000000..94ebd9e --- /dev/null +++ b/packages/asset-manager/src/file.ts @@ -0,0 +1,17 @@ +export class NfFile { + private readonly _path: string; + + constructor(path: string) { + this._path = path; + } + + get path(): string { + return this._path; + } + + public async getText(): Promise { + const res = await fetch(this._path); + if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); + return await res.text(); + } +} diff --git a/packages/asset-manager/src/index.ts b/packages/asset-manager/src/index.ts new file mode 100644 index 0000000..d372550 --- /dev/null +++ b/packages/asset-manager/src/index.ts @@ -0,0 +1,2 @@ +export { AssetManagerLibrary } from "./asset-manager.library"; +export { NfFile } from "./file"; diff --git a/packages/asset-manager/test/asset-manager.library.spec.ts b/packages/asset-manager/test/asset-manager.library.spec.ts new file mode 100644 index 0000000..52c420f --- /dev/null +++ b/packages/asset-manager/test/asset-manager.library.spec.ts @@ -0,0 +1,49 @@ +import { ApplicationContext, InitContext, LibraryManager } from "@nanoforge/common"; + +import { AssetManagerLibrary } from "../src"; + +describe("Asset Manager Library", () => { + const library = new AssetManagerLibrary(); + const appContext = new ApplicationContext(); + const libraryManager = new LibraryManager(); + const context = new InitContext(appContext, libraryManager, { + // @ts-ignore + canvas: null, + files: { + assets: new Map([["/test.png", "blob:http://localhost:3000/test.png"]]), + wasm: new Map([["/test.wasm", "blob:http://localhost:3000/test.wasm"]]), + wgsl: new Map([["/test.wgsl", "blob:http://localhost:3000/test.wgsl"]]), + }, + }); + library.init(context); + + it("Should get asset", async () => { + expect((await library.getAsset("test.png")).path).toEqual( + "blob:http://localhost:3000/test.png", + ); + }); + + it("Should throw on unknown asset", async () => { + await expect(library.getAsset("test-unknown.png")).rejects.toThrow(); + }); + + it("Should get wasm", async () => { + expect((await library.getWasm("test.wasm")).path).toEqual( + "blob:http://localhost:3000/test.wasm", + ); + }); + + it("Should throw on unknown wasm", async () => { + await expect(library.getWasm("test-unknown.wasm")).rejects.toThrow(); + }); + + it("Should get wgsl", async () => { + expect((await library.getWgsl("test.wgsl")).path).toEqual( + "blob:http://localhost:3000/test.wgsl", + ); + }); + + it("Should throw on unknown wgsl", async () => { + await expect(library.getWgsl("test-unknown.wgsl")).rejects.toThrow(); + }); +}); diff --git a/packages/asset-manager/test/tsconfig.json b/packages/asset-manager/test/tsconfig.json new file mode 100644 index 0000000..50d5966 --- /dev/null +++ b/packages/asset-manager/test/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../../tsconfig.spec.json" +} diff --git a/packages/asset-manager/tsconfig.build.json b/packages/asset-manager/tsconfig.build.json new file mode 100644 index 0000000..a7e09c7 --- /dev/null +++ b/packages/asset-manager/tsconfig.build.json @@ -0,0 +1,16 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "outDir": ".", + "rootDir": ".", + "paths": { + "@nanoforge/common": ["../common"] + } + }, + "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], + "references": [ + { + "path": "../common/tsconfig.build.json" + } + ] +} diff --git a/packages/asset-manager/tsconfig.json b/packages/asset-manager/tsconfig.json new file mode 100644 index 0000000..a74c8e2 --- /dev/null +++ b/packages/asset-manager/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "types": ["jest", "node"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.build.json" + } + ] +} diff --git a/packages/common/.idea/.gitignore b/packages/common/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/packages/common/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/packages/common/.idea/.name b/packages/common/.idea/.name new file mode 100644 index 0000000..e68a453 --- /dev/null +++ b/packages/common/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine Common \ No newline at end of file diff --git a/packages/common/.idea/[NanoForge] Engine Common.iml b/packages/common/.idea/[NanoForge] Engine Common.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/packages/common/.idea/[NanoForge] Engine Common.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/common/.idea/codeStyles/Project.xml b/packages/common/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..b70d753 --- /dev/null +++ b/packages/common/.idea/codeStyles/Project.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/common/.idea/codeStyles/codeStyleConfig.xml b/packages/common/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/packages/common/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/common/.idea/git_toolbox_blame.xml b/packages/common/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/packages/common/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/common/.idea/git_toolbox_prj.xml b/packages/common/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/packages/common/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/common/.idea/inspectionProfiles/Project_Default.xml b/packages/common/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/packages/common/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/packages/common/.idea/jsLinters/eslint.xml b/packages/common/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/packages/common/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/common/.idea/modules.xml b/packages/common/.idea/modules.xml new file mode 100644 index 0000000..78a7828 --- /dev/null +++ b/packages/common/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/common/.idea/prettier.xml b/packages/common/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/packages/common/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/packages/common/.idea/vcs.xml b/packages/common/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/packages/common/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/common/src/context/contexts/application.context.ts b/packages/common/src/context/contexts/application.context.ts new file mode 100644 index 0000000..9ec3573 --- /dev/null +++ b/packages/common/src/context/contexts/application.context.ts @@ -0,0 +1 @@ +export class ApplicationContext {} diff --git a/packages/common/src/context/contexts/executions/base.context.ts b/packages/common/src/context/contexts/executions/base.context.ts new file mode 100644 index 0000000..c6917f4 --- /dev/null +++ b/packages/common/src/context/contexts/executions/base.context.ts @@ -0,0 +1,20 @@ +import { type LibraryManager } from "../../../library/manager/managers/library.manager"; +import { type ApplicationContext } from "../application.context"; + +export class BaseContext { + private readonly _applicationContext: ApplicationContext; + private readonly _libraryManager: LibraryManager; + + constructor(applicationContext: ApplicationContext, libraryManager: LibraryManager) { + this._applicationContext = applicationContext; + this._libraryManager = libraryManager; + } + + get application(): ApplicationContext { + return this._applicationContext; + } + + get libraries(): LibraryManager { + return this._libraryManager; + } +} diff --git a/packages/common/src/context/contexts/executions/clear.context.ts b/packages/common/src/context/contexts/executions/clear.context.ts new file mode 100644 index 0000000..6755dc8 --- /dev/null +++ b/packages/common/src/context/contexts/executions/clear.context.ts @@ -0,0 +1,3 @@ +import { BaseContext } from "./base.context"; + +export class ClearContext extends BaseContext {} diff --git a/packages/common/src/context/contexts/executions/execution.context.ts b/packages/common/src/context/contexts/executions/execution.context.ts new file mode 100644 index 0000000..00e2a34 --- /dev/null +++ b/packages/common/src/context/contexts/executions/execution.context.ts @@ -0,0 +1,9 @@ +import { BaseContext } from "./base.context"; + +export class ExecutionContext extends BaseContext { + protected _isRunning: boolean = true; + + get isRunning() { + return this._isRunning; + } +} diff --git a/packages/common/src/context/contexts/executions/index.ts b/packages/common/src/context/contexts/executions/index.ts new file mode 100644 index 0000000..25d298b --- /dev/null +++ b/packages/common/src/context/contexts/executions/index.ts @@ -0,0 +1,3 @@ +export { ClearContext } from "./clear.context"; +export { ExecutionContext } from "./execution.context"; +export { InitContext } from "./init.context"; diff --git a/packages/common/src/context/contexts/executions/init.context.ts b/packages/common/src/context/contexts/executions/init.context.ts new file mode 100644 index 0000000..ec43400 --- /dev/null +++ b/packages/common/src/context/contexts/executions/init.context.ts @@ -0,0 +1,24 @@ +import { type LibraryManager } from "../../../library"; +import { type IRunOptions } from "../../../options"; +import { type ApplicationContext } from "../application.context"; +import { BaseContext } from "./base.context"; + +export class InitContext extends BaseContext { + private readonly _canvas: IRunOptions["canvas"]; + private readonly _files: IRunOptions["files"]; + + constructor(context: ApplicationContext, libraryManager: LibraryManager, options: IRunOptions) { + super(context, libraryManager); + + this._canvas = options.canvas; + this._files = options.files; + } + + get canvas(): IRunOptions["canvas"] { + return this._canvas; + } + + get files(): IRunOptions["files"] { + return this._files; + } +} diff --git a/packages/common/src/context/contexts/index.ts b/packages/common/src/context/contexts/index.ts new file mode 100644 index 0000000..3fc9395 --- /dev/null +++ b/packages/common/src/context/contexts/index.ts @@ -0,0 +1,3 @@ +export * from "./executions"; +export { ApplicationContext } from "./application.context"; +export { LibraryContext, LibraryStatusEnum } from "./library.context"; diff --git a/packages/common/src/context/contexts/library.context.ts b/packages/common/src/context/contexts/library.context.ts new file mode 100644 index 0000000..92ae7fb --- /dev/null +++ b/packages/common/src/context/contexts/library.context.ts @@ -0,0 +1,13 @@ +export enum LibraryStatusEnum { + UNLOADED = "UNLOADED", + LOADED = "LOADED", + CLEAR = "CLEAR", +} + +export class LibraryContext { + protected _status: LibraryStatusEnum; + + get status() { + return this._status; + } +} diff --git a/packages/common/src/context/index.ts b/packages/common/src/context/index.ts new file mode 100644 index 0000000..315ff97 --- /dev/null +++ b/packages/common/src/context/index.ts @@ -0,0 +1 @@ +export * from "./contexts"; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index b98b4c7..12d9d7a 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1 +1,3 @@ -export interface ILibrary {} +export * from "./context"; +export * from "./library"; +export * from "./options"; diff --git a/packages/common/src/library/index.ts b/packages/common/src/library/index.ts new file mode 100644 index 0000000..569fe70 --- /dev/null +++ b/packages/common/src/library/index.ts @@ -0,0 +1,2 @@ +export * from "./libraries"; +export * from "./manager"; diff --git a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts new file mode 100644 index 0000000..6f6d027 --- /dev/null +++ b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts @@ -0,0 +1,7 @@ +import { type InitContext } from "../../../context"; +import { type IAssetManagerLibrary } from "../interfaces"; +import { Library } from "../library"; + +export abstract class BaseAssetManagerLibrary extends Library implements IAssetManagerLibrary { + public abstract init(context: InitContext): Promise; +} diff --git a/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts b/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts new file mode 100644 index 0000000..68a59d7 --- /dev/null +++ b/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts @@ -0,0 +1,10 @@ +import { type ExecutionContext } from "../../../context"; +import { type IComponentSystemLibrary } from "../interfaces"; +import { Library } from "../library"; + +export abstract class BaseComponentSystemLibrary + extends Library + implements IComponentSystemLibrary +{ + abstract run(context: ExecutionContext): Promise; +} diff --git a/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts b/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts new file mode 100644 index 0000000..bf95912 --- /dev/null +++ b/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts @@ -0,0 +1,7 @@ +import type { ExecutionContext } from "../../../context"; +import { type IGraphicsLibrary } from "../interfaces"; +import { Library } from "../library"; + +export abstract class BaseGraphicsLibrary extends Library implements IGraphicsLibrary { + abstract run(context: ExecutionContext): Promise; +} diff --git a/packages/common/src/library/libraries/abstracts/index.ts b/packages/common/src/library/libraries/abstracts/index.ts new file mode 100644 index 0000000..7d2d8a1 --- /dev/null +++ b/packages/common/src/library/libraries/abstracts/index.ts @@ -0,0 +1,5 @@ +export { BaseAssetManagerLibrary } from "./asset-manager.library.abstract"; +export { BaseComponentSystemLibrary } from "./component-system.library.abstract"; +export { BaseGraphicsLibrary } from "./graphics.library.abstract"; +export { BaseInputLibrary } from "./input.library.abstract"; +export { BaseNetworkLibrary } from "./network.library.abstract"; diff --git a/packages/common/src/library/libraries/abstracts/input.library.abstract.ts b/packages/common/src/library/libraries/abstracts/input.library.abstract.ts new file mode 100644 index 0000000..afa8a19 --- /dev/null +++ b/packages/common/src/library/libraries/abstracts/input.library.abstract.ts @@ -0,0 +1,7 @@ +import { type InitContext } from "../../../context"; +import { type IInputLibrary } from "../interfaces"; +import { Library } from "../library"; + +export abstract class BaseInputLibrary extends Library implements IInputLibrary { + public abstract init(context: InitContext): Promise; +} diff --git a/packages/common/src/library/libraries/abstracts/network.library.abstract.ts b/packages/common/src/library/libraries/abstracts/network.library.abstract.ts new file mode 100644 index 0000000..c32ffde --- /dev/null +++ b/packages/common/src/library/libraries/abstracts/network.library.abstract.ts @@ -0,0 +1,4 @@ +import { type INetworkLibrary } from "../interfaces"; +import { Library } from "../library"; + +export abstract class BaseNetworkLibrary extends Library implements INetworkLibrary {} diff --git a/packages/common/src/library/libraries/consts/index.ts b/packages/common/src/library/libraries/consts/index.ts new file mode 100644 index 0000000..e8609d9 --- /dev/null +++ b/packages/common/src/library/libraries/consts/index.ts @@ -0,0 +1 @@ +export * from "./library-label.const"; diff --git a/packages/common/src/library/libraries/consts/library-label.const.ts b/packages/common/src/library/libraries/consts/library-label.const.ts new file mode 100644 index 0000000..0e487ff --- /dev/null +++ b/packages/common/src/library/libraries/consts/library-label.const.ts @@ -0,0 +1,5 @@ +export const COMPONENT_SYSTEM_LIBRARY = Symbol("COMPONENT_SYSTEM_LIBRARY"); +export const GRAPHICS_LIBRARY = Symbol("GRAPHICS_LIBRARY"); +export const NETWORK_LIBRARY = Symbol("NETWORK_LIBRARY"); +export const ASSET_MANAGER_LIBRARY = Symbol("ASSET_MANAGER_LIBRARY"); +export const INPUT_LIBRARY = Symbol("INPUT_LIBRARY"); diff --git a/packages/common/src/library/libraries/index.ts b/packages/common/src/library/libraries/index.ts new file mode 100644 index 0000000..9673f88 --- /dev/null +++ b/packages/common/src/library/libraries/index.ts @@ -0,0 +1,5 @@ +export { ILibrary } from "./library.type"; + +export * from "./abstracts"; +export * from "./consts"; +export * from "./interfaces"; diff --git a/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts b/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts new file mode 100644 index 0000000..d72f9f1 --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts @@ -0,0 +1,3 @@ +import { type ILibrary } from "../../library.type"; + +export interface IExposedLibrary extends ILibrary {} diff --git a/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts b/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts new file mode 100644 index 0000000..8c04831 --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts @@ -0,0 +1,6 @@ +import { type ExecutionContext } from "../../../../context"; +import { type ILibrary } from "../../library.type"; + +export interface IRunnerLibrary extends ILibrary { + run(context: ExecutionContext): Promise; +} diff --git a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts new file mode 100644 index 0000000..7348904 --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts @@ -0,0 +1,3 @@ +import { type IExposedLibrary } from "../bases/exposed.library.type"; + +export interface IAssetManagerLibrary extends IExposedLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts new file mode 100644 index 0000000..30be76e --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts @@ -0,0 +1,4 @@ +import { type IExposedLibrary } from "../bases/exposed.library.type"; +import { type IRunnerLibrary } from "../bases/runner.library.type"; + +export interface IComponentSystemLibrary extends IExposedLibrary, IRunnerLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts new file mode 100644 index 0000000..8023a65 --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts @@ -0,0 +1,4 @@ +import { type IExposedLibrary } from "../bases/exposed.library.type"; +import { type IRunnerLibrary } from "../bases/runner.library.type"; + +export interface IGraphicsLibrary extends IExposedLibrary, IRunnerLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts new file mode 100644 index 0000000..596a519 --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts @@ -0,0 +1,3 @@ +import { type IExposedLibrary } from "../bases/exposed.library.type"; + +export interface IInputLibrary extends IExposedLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts new file mode 100644 index 0000000..4ad23ad --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts @@ -0,0 +1,3 @@ +import { type IExposedLibrary } from "../bases/exposed.library.type"; + +export interface INetworkLibrary extends IExposedLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/index.ts b/packages/common/src/library/libraries/interfaces/index.ts new file mode 100644 index 0000000..50807a1 --- /dev/null +++ b/packages/common/src/library/libraries/interfaces/index.ts @@ -0,0 +1,7 @@ +export { IExposedLibrary } from "./bases/exposed.library.type"; +export { IRunnerLibrary } from "./bases/runner.library.type"; +export { IAssetManagerLibrary } from "./finals/asset-manager.library.type"; +export { IComponentSystemLibrary } from "./finals/component-system.library.type"; +export { IGraphicsLibrary } from "./finals/graphics.library.type"; +export { IInputLibrary } from "./finals/input.library.type"; +export { INetworkLibrary } from "./finals/network.library.type"; diff --git a/packages/common/src/library/libraries/library.ts b/packages/common/src/library/libraries/library.ts new file mode 100644 index 0000000..744094a --- /dev/null +++ b/packages/common/src/library/libraries/library.ts @@ -0,0 +1,12 @@ +import { type ClearContext, type InitContext } from "../../context"; +import { type ILibrary } from "./library.type"; + +export abstract class Library implements ILibrary { + abstract get name(): string; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async init(_context: InitContext): Promise {} + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async clear(_context: ClearContext): Promise {} +} diff --git a/packages/common/src/library/libraries/library.type.ts b/packages/common/src/library/libraries/library.type.ts new file mode 100644 index 0000000..c9913bc --- /dev/null +++ b/packages/common/src/library/libraries/library.type.ts @@ -0,0 +1,9 @@ +import { type ApplicationContext, type ClearContext } from "../../context"; + +export interface ILibrary { + get name(): string; + + init(context: ApplicationContext): Promise; + + clear(context: ClearContext): Promise; +} diff --git a/packages/common/src/library/manager/handle/library.handle.ts b/packages/common/src/library/manager/handle/library.handle.ts new file mode 100644 index 0000000..ee24361 --- /dev/null +++ b/packages/common/src/library/manager/handle/library.handle.ts @@ -0,0 +1,26 @@ +import { type LibraryContext } from "../../../context"; +import { type ILibrary } from "../../libraries/library.type"; + +export class LibraryHandle { + private readonly _symbol: symbol; + private readonly _library: T; + private readonly _context: LibraryContext; + + constructor(sym: symbol, library: T, defaultContext: LibraryContext) { + this._symbol = sym; + this._library = library; + this._context = defaultContext; + } + + get symbol(): symbol { + return this._symbol; + } + + get library(): T { + return this._library; + } + + get context(): LibraryContext { + return this._context; + } +} diff --git a/packages/common/src/library/manager/index.ts b/packages/common/src/library/manager/index.ts new file mode 100644 index 0000000..7bfd452 --- /dev/null +++ b/packages/common/src/library/manager/index.ts @@ -0,0 +1,2 @@ +export { LibraryHandle } from "./handle/library.handle"; +export { DefaultLibrariesEnum, LibraryManager } from "./managers/library.manager"; diff --git a/packages/common/src/library/manager/managers/base-library.manager.ts b/packages/common/src/library/manager/managers/base-library.manager.ts new file mode 100644 index 0000000..418e607 --- /dev/null +++ b/packages/common/src/library/manager/managers/base-library.manager.ts @@ -0,0 +1,39 @@ +import { type LibraryContext } from "../../../context"; +import { type ILibrary } from "../../libraries"; +import { LibraryHandle } from "../handle/library.handle"; + +export class BaseLibraryManager { + protected _libraries: LibraryHandle[] = []; + private _librariesIndex: { + [sym: symbol]: number; + }; + + /** + * @todo Add error management + */ + public get(sym: symbol): LibraryHandle { + const index = this._librariesIndex[sym]; + if (!index) throw new Error(`Library not found: ${Symbol.keyFor(sym)}`); + return this._get(index, sym); + } + + protected setNewLibrary(sym: symbol, library: ILibrary, context: LibraryContext): void { + const index = this._libraries.length; + this._setIndex(sym, index); + this._set(index, sym, library, context); + } + + protected _get(index: number, sym?: symbol): LibraryHandle { + const result = this._libraries[index]; + if (!result) throw new Error(`Library not found: ${sym ? Symbol.keyFor(sym) : index}`); + return result as LibraryHandle; + } + + protected _set(index: number, sym: symbol, library: ILibrary, context: LibraryContext): void { + this._libraries[index] = new LibraryHandle(sym, library, context); + } + + protected _setIndex(sym: symbol, index: number): void { + if (Symbol.keyFor(sym)) this._librariesIndex[sym] = index; + } +} diff --git a/packages/common/src/library/manager/managers/library.manager.ts b/packages/common/src/library/manager/managers/library.manager.ts new file mode 100644 index 0000000..2aa8f01 --- /dev/null +++ b/packages/common/src/library/manager/managers/library.manager.ts @@ -0,0 +1,62 @@ +import { + ASSET_MANAGER_LIBRARY, + COMPONENT_SYSTEM_LIBRARY, + GRAPHICS_LIBRARY, + type IAssetManagerLibrary, + type IComponentSystemLibrary, + type IGraphicsLibrary, + type IInputLibrary, + type INetworkLibrary, + NETWORK_LIBRARY, +} from "../../libraries"; +import { type LibraryHandle } from "../handle/library.handle"; +import { BaseLibraryManager } from "./base-library.manager"; + +export enum DefaultLibrariesEnum { + ASSET_MANAGER, + INPUT, + COMPONENT_SYSTEM, + NETWORK, + GRAPHICS, +} + +const DEFAULT_LIBRARIES: { index: DefaultLibrariesEnum; sym: symbol }[] = [ + { index: DefaultLibrariesEnum.ASSET_MANAGER, sym: ASSET_MANAGER_LIBRARY }, + { index: DefaultLibrariesEnum.COMPONENT_SYSTEM, sym: COMPONENT_SYSTEM_LIBRARY }, + { index: DefaultLibrariesEnum.NETWORK, sym: NETWORK_LIBRARY }, + { index: DefaultLibrariesEnum.GRAPHICS, sym: GRAPHICS_LIBRARY }, +]; + +export class LibraryManager extends BaseLibraryManager { + constructor() { + super(); + + for (const { index, sym } of DEFAULT_LIBRARIES) { + this._setIndex(sym, index); + } + } + + public getComponentSystem< + T extends IComponentSystemLibrary = IComponentSystemLibrary, + >(): LibraryHandle { + return this._get(DefaultLibrariesEnum.COMPONENT_SYSTEM); + } + + public getGraphics(): LibraryHandle { + return this._get(DefaultLibrariesEnum.GRAPHICS); + } + + public getNetwork(): LibraryHandle { + return this._get(DefaultLibrariesEnum.NETWORK); + } + + public getInput(): LibraryHandle { + return this._get(DefaultLibrariesEnum.INPUT); + } + + public getAssetManager< + T extends IAssetManagerLibrary = IAssetManagerLibrary, + >(): LibraryHandle { + return this._get(DefaultLibrariesEnum.ASSET_MANAGER); + } +} diff --git a/packages/common/src/options/index.ts b/packages/common/src/options/index.ts new file mode 100644 index 0000000..75f33f2 --- /dev/null +++ b/packages/common/src/options/index.ts @@ -0,0 +1 @@ +export { IRunOptions } from "./types/options.type"; diff --git a/packages/common/src/options/types/options.type.ts b/packages/common/src/options/types/options.type.ts new file mode 100644 index 0000000..b0a02e3 --- /dev/null +++ b/packages/common/src/options/types/options.type.ts @@ -0,0 +1,8 @@ +export interface IRunOptions { + canvas: HTMLCanvasElement; + files: { + assets: Map; + wasm: Map; + wgsl: Map; + }; +} diff --git a/packages/core/.idea/.name b/packages/core/.idea/.name new file mode 100644 index 0000000..3d3e7ca --- /dev/null +++ b/packages/core/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine Core \ No newline at end of file diff --git a/packages/core/.idea/[NanoForge] Engine Core.iml b/packages/core/.idea/[NanoForge] Engine Core.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/packages/core/.idea/[NanoForge] Engine Core.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/core/.idea/codeStyles/Project.xml b/packages/core/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..b70d753 --- /dev/null +++ b/packages/core/.idea/codeStyles/Project.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/core/.idea/codeStyles/codeStyleConfig.xml b/packages/core/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/packages/core/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/core/.idea/git_toolbox_blame.xml b/packages/core/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/packages/core/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/core/.idea/git_toolbox_prj.xml b/packages/core/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/packages/core/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/core/.idea/inspectionProfiles/Project_Default.xml b/packages/core/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/packages/core/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/packages/core/.idea/jsLinters/eslint.xml b/packages/core/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/packages/core/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/core/.idea/modules.xml b/packages/core/.idea/modules.xml new file mode 100644 index 0000000..99922e2 --- /dev/null +++ b/packages/core/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/core/.idea/prettier.xml b/packages/core/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/packages/core/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/packages/core/.idea/vcs.xml b/packages/core/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/packages/core/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/core/src/application/application-config.ts b/packages/core/src/application/application-config.ts new file mode 100644 index 0000000..e29dbbd --- /dev/null +++ b/packages/core/src/application/application-config.ts @@ -0,0 +1,71 @@ +import { + type IAssetManagerLibrary, + type IComponentSystemLibrary, + type IGraphicsLibrary, + type IInputLibrary, + type ILibrary, + type INetworkLibrary, + type LibraryHandle, +} from "@nanoforge/common"; + +import { EditableLibraryManager } from "../common/library/manager/library.manager"; + +export class ApplicationConfig { + private readonly _libraryManager: EditableLibraryManager; + + constructor() { + this._libraryManager = new EditableLibraryManager(); + } + + get libraryManager(): EditableLibraryManager { + return this._libraryManager; + } + + public getLibrary(sym: symbol): LibraryHandle { + return this._libraryManager.get(sym); + } + + public useLibrary(sym: symbol, library: ILibrary): void { + this._libraryManager.set(sym, library); + } + + public getComponentSystemLibrary() { + return this._libraryManager.getComponentSystem(); + } + + public useComponentSystemLibrary(library: IComponentSystemLibrary) { + this._libraryManager.setComponentSystem(library); + } + + public getGraphicsLibrary() { + return this._libraryManager.getGraphics(); + } + + public useGraphicsLibrary(library: IGraphicsLibrary) { + this._libraryManager.setGraphics(library); + } + + public getNetworkLibrary() { + return this._libraryManager.getNetwork(); + } + + public useNetworkLibrary(library: INetworkLibrary) { + this._libraryManager.setNetwork(library); + } + + public getAssetManagerLibrary() { + return this._libraryManager.getAssetManager(); + } + + public useAssetManagerLibrary(library: IAssetManagerLibrary) { + this._libraryManager.setAssetManager(library); + } + + public getInputLibrary() { + return this._libraryManager.getInput(); + } + + public useInputLibrary(library: IInputLibrary) { + this._libraryManager.setInput(library); + } +} diff --git a/packages/core/src/application/application-options.type.ts b/packages/core/src/application/application-options.type.ts new file mode 100644 index 0000000..57ecc83 --- /dev/null +++ b/packages/core/src/application/application-options.type.ts @@ -0,0 +1,3 @@ +export interface IApplicationOptions { + tickRate: number; +} diff --git a/packages/core/src/application/nanoforge-application.ts b/packages/core/src/application/nanoforge-application.ts new file mode 100644 index 0000000..4684380 --- /dev/null +++ b/packages/core/src/application/nanoforge-application.ts @@ -0,0 +1,54 @@ +import { + ApplicationContext, + type IAssetManagerLibrary, + type IComponentSystemLibrary, + type ILibrary, + type INetworkLibrary, + type IRunOptions, +} from "@nanoforge/common"; + +import { Core } from "../core/core"; +import { ApplicationConfig } from "./application-config"; +import type { IApplicationOptions } from "./application-options.type"; + +export abstract class NanoforgeApplication { + protected applicationConfig: ApplicationConfig; + private _core: Core; + private readonly _options: IApplicationOptions; + + constructor(options?: Partial) { + this.applicationConfig = new ApplicationConfig(); + + this._options = { + tickRate: 60, + ...(options ?? {}), + }; + } + + public use(sym: symbol, library: ILibrary): void { + this.applicationConfig.useLibrary(sym, library); + } + + public useComponentSystem(library: IComponentSystemLibrary) { + this.applicationConfig.useComponentSystemLibrary(library); + } + + public useNetwork(library: INetworkLibrary) { + this.applicationConfig.useNetworkLibrary(library); + } + + public useAssetManager(library: IAssetManagerLibrary) { + this.applicationConfig.useAssetManagerLibrary(library); + } + + public async init(options: IRunOptions): Promise { + this._core = new Core(this.applicationConfig, new ApplicationContext()); + await this._core.init(options, this._options); + } + + public run() { + this._core.run().then(() => { + console.info("Game ended successfully."); + }); + } +} diff --git a/packages/core/src/application/nanoforge-client.ts b/packages/core/src/application/nanoforge-client.ts new file mode 100644 index 0000000..66d0534 --- /dev/null +++ b/packages/core/src/application/nanoforge-client.ts @@ -0,0 +1,13 @@ +import { type IGraphicsLibrary, type IInputLibrary } from "@nanoforge/common"; + +import { NanoforgeApplication } from "./nanoforge-application"; + +export class NanoforgeClient extends NanoforgeApplication { + public useGraphics(library: IGraphicsLibrary) { + this.applicationConfig.useGraphicsLibrary(library); + } + + public useInput(library: IInputLibrary) { + this.applicationConfig.useInputLibrary(library); + } +} diff --git a/packages/core/src/application/nanoforge-factory.ts b/packages/core/src/application/nanoforge-factory.ts new file mode 100644 index 0000000..84711a6 --- /dev/null +++ b/packages/core/src/application/nanoforge-factory.ts @@ -0,0 +1,15 @@ +import { type IApplicationOptions } from "./application-options.type"; +import { NanoforgeClient } from "./nanoforge-client"; +import { NanoforgeServer } from "./nanoforge-server"; + +class NanoforgeFactoryStatic { + createClient(options?: Partial): NanoforgeClient { + return new NanoforgeClient(options); + } + + createServer(options?: Partial): NanoforgeServer { + return new NanoforgeServer(options); + } +} + +export const NanoforgeFactory = new NanoforgeFactoryStatic(); diff --git a/packages/core/src/application/nanoforge-server.ts b/packages/core/src/application/nanoforge-server.ts new file mode 100644 index 0000000..74cca8a --- /dev/null +++ b/packages/core/src/application/nanoforge-server.ts @@ -0,0 +1,3 @@ +import { NanoforgeApplication } from "./nanoforge-application"; + +export class NanoforgeServer extends NanoforgeApplication {} diff --git a/packages/core/src/common/context/contexts/application.editable-context.ts b/packages/core/src/common/context/contexts/application.editable-context.ts new file mode 100644 index 0000000..6288f1a --- /dev/null +++ b/packages/core/src/common/context/contexts/application.editable-context.ts @@ -0,0 +1,3 @@ +import { ApplicationContext } from "@nanoforge/common"; + +export class EditableApplicationContext extends ApplicationContext {} diff --git a/packages/core/src/common/context/contexts/executions/clear.editable-context.ts b/packages/core/src/common/context/contexts/executions/clear.editable-context.ts new file mode 100644 index 0000000..8174c1b --- /dev/null +++ b/packages/core/src/common/context/contexts/executions/clear.editable-context.ts @@ -0,0 +1,3 @@ +import { ClearContext } from "@nanoforge/common"; + +export class EditableClearContext extends ClearContext {} diff --git a/packages/core/src/common/context/contexts/executions/execution.editable-context.ts b/packages/core/src/common/context/contexts/executions/execution.editable-context.ts new file mode 100644 index 0000000..d6b2d96 --- /dev/null +++ b/packages/core/src/common/context/contexts/executions/execution.editable-context.ts @@ -0,0 +1,7 @@ +import { ExecutionContext } from "@nanoforge/common"; + +export class EditableExecutionContext extends ExecutionContext { + setIsRunning(isRunning: boolean) { + this._isRunning = isRunning; + } +} diff --git a/packages/core/src/common/context/contexts/executions/init.editable-context.ts b/packages/core/src/common/context/contexts/executions/init.editable-context.ts new file mode 100644 index 0000000..966c70e --- /dev/null +++ b/packages/core/src/common/context/contexts/executions/init.editable-context.ts @@ -0,0 +1,3 @@ +import { InitContext } from "@nanoforge/common"; + +export class EditableInitContext extends InitContext {} diff --git a/packages/core/src/common/context/contexts/library.editable-context.ts b/packages/core/src/common/context/contexts/library.editable-context.ts new file mode 100644 index 0000000..27f3e95 --- /dev/null +++ b/packages/core/src/common/context/contexts/library.editable-context.ts @@ -0,0 +1,7 @@ +import { LibraryContext, type LibraryStatusEnum } from "@nanoforge/common"; + +export class EditableLibraryContext extends LibraryContext { + setStatus(status: LibraryStatusEnum) { + this._status = status; + } +} diff --git a/packages/core/src/common/library/manager/library.manager.ts b/packages/core/src/common/library/manager/library.manager.ts new file mode 100644 index 0000000..8f6090e --- /dev/null +++ b/packages/core/src/common/library/manager/library.manager.ts @@ -0,0 +1,70 @@ +import { + ASSET_MANAGER_LIBRARY, + COMPONENT_SYSTEM_LIBRARY, + DefaultLibrariesEnum, + GRAPHICS_LIBRARY, + type IAssetManagerLibrary, + type IComponentSystemLibrary, + type IGraphicsLibrary, + type IInputLibrary, + type ILibrary, + INPUT_LIBRARY, + type INetworkLibrary, + type IRunnerLibrary, + type LibraryHandle, + LibraryManager, + NETWORK_LIBRARY, +} from "@nanoforge/common"; + +import { EditableLibraryContext } from "../../context/contexts/library.editable-context"; + +export class EditableLibraryManager extends LibraryManager { + public set(sym: symbol, library: ILibrary) { + this.setNewLibrary(sym, library, new EditableLibraryContext()); + } + + public setComponentSystem(library: IComponentSystemLibrary): void { + this._set( + DefaultLibrariesEnum.COMPONENT_SYSTEM, + COMPONENT_SYSTEM_LIBRARY, + library, + new EditableLibraryContext(), + ); + } + + public setGraphics(library: IGraphicsLibrary): void { + this._set( + DefaultLibrariesEnum.GRAPHICS, + GRAPHICS_LIBRARY, + library, + new EditableLibraryContext(), + ); + } + + public setAssetManager(library: IAssetManagerLibrary): void { + this._set( + DefaultLibrariesEnum.ASSET_MANAGER, + ASSET_MANAGER_LIBRARY, + library, + new EditableLibraryContext(), + ); + } + + public setNetwork(library: INetworkLibrary): void { + this._set(DefaultLibrariesEnum.NETWORK, NETWORK_LIBRARY, library, new EditableLibraryContext()); + } + + public setInput(library: IInputLibrary): void { + this._set(DefaultLibrariesEnum.INPUT, INPUT_LIBRARY, library, new EditableLibraryContext()); + } + + public getLibraries(): LibraryHandle[] { + return this._libraries; + } + + public getRunnerLibraries(): LibraryHandle[] { + return this._libraries.filter( + (handle) => handle && typeof handle.library["run"] === "function", + ) as LibraryHandle[]; + } +} diff --git a/packages/core/src/core/core.ts b/packages/core/src/core/core.ts new file mode 100644 index 0000000..6196cd1 --- /dev/null +++ b/packages/core/src/core/core.ts @@ -0,0 +1,79 @@ +import { + type ApplicationContext, + ClearContext, + ExecutionContext, + type IRunOptions, + type IRunnerLibrary, + InitContext, + type LibraryHandle, +} from "@nanoforge/common"; + +import { type ApplicationConfig } from "../application/application-config"; +import type { IApplicationOptions } from "../application/application-options.type"; + +export class Core { + private readonly config: ApplicationConfig; + private readonly context: ApplicationContext; + private options: IApplicationOptions; + + constructor(config: ApplicationConfig, context: ApplicationContext) { + this.config = config; + this.context = context; + } + + public async init(options: IRunOptions, appOptions: IApplicationOptions): Promise { + this.options = appOptions; + await this.runInit(this.getInitContext(options)); + } + + public async run(): Promise { + const context = this.getExecutionContext(); + const libraries = this.config.libraryManager.getRunnerLibraries(); + let requestAnimationFrameHandle: number; + + const runner = async () => { + await this.runExecute(context, libraries); + }; + + const render = () => { + if (!context.isRunning) { + clearInterval(intervalHandle); + return; + } + cancelAnimationFrame(requestAnimationFrameHandle); + requestAnimationFrameHandle = requestAnimationFrame(runner); + }; + + const intervalHandle = setInterval(render, 1000 / this.options.tickRate); + } + + private getInitContext(options: IRunOptions): InitContext { + return new InitContext(this.context, this.config.libraryManager, options); + } + + private getExecutionContext(): ExecutionContext { + return new ExecutionContext(this.context, this.config.libraryManager); + } + + private getClearContext(): ClearContext { + return new ClearContext(this.context, this.config.libraryManager); + } + + private async runInit(context: InitContext): Promise { + for (const handle of this.config.libraryManager.getLibraries()) { + if (handle) await handle.library.init(context); + } + } + + private async runExecute(context: ExecutionContext, libraries: LibraryHandle[]) { + for (const handle of libraries) { + if (handle) await handle.library.run(context); + } + } + + private runClear(context: ClearContext) { + for (const handle of this.config.libraryManager.getLibraries()) { + if (handle) handle.library.clear(context); + } + } +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index bf6ca3f..2931fb7 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1 +1 @@ -export * from "./nanoforge-engine"; +export * from "./application/nanoforge-factory"; diff --git a/packages/core/src/nanoforge-engine.ts b/packages/core/src/nanoforge-engine.ts deleted file mode 100644 index 9dd2ca3..0000000 --- a/packages/core/src/nanoforge-engine.ts +++ /dev/null @@ -1 +0,0 @@ -export class NanoForgeEngine {} diff --git a/packages/core/tsconfig.build.json b/packages/core/tsconfig.build.json index 2e31798..a7e09c7 100644 --- a/packages/core/tsconfig.build.json +++ b/packages/core/tsconfig.build.json @@ -4,8 +4,7 @@ "outDir": ".", "rootDir": ".", "paths": { - "@nanoforge/common": ["../common"], - "@nanoforge/common/*": ["../common/*"] + "@nanoforge/common": ["../common"] } }, "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], diff --git a/packages/ecs/.clang-format b/packages/ecs/.clang-format new file mode 100644 index 0000000..ad80c57 --- /dev/null +++ b/packages/ecs/.clang-format @@ -0,0 +1,63 @@ +IndentWidth: 4 + +ColumnLimit: 160 + +# function names +AlignAfterOpenBracket: BlockIndent +AllowAllArgumentsOnNextLine: true +IndentWrappedFunctionNames: false +AlignOperands: false +SeparateDefinitionBlocks: Always + +# prevent break between return type and function decl +PenaltyReturnTypeOnItsOwnLine: 10000 +InsertNewlineAtEOF: true +AllowShortFunctionsOnASingleLine: Empty + +# braces placement +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterStruct: false + AfterUnion: false + BeforeElse: false + IndentBraces: false +AlignEscapedNewlines: DontAlign + +# pointers +PointerAlignment: Right +SpacesInCStyleCastParentheses: false +SpaceAfterCStyleCast: false +ReferenceAlignment: Right + +# includes +IndentPPDirectives: BeforeHash + +SortIncludes: true +IncludeBlocks: Preserve + +IncludeCategories: + - Regex: '^"[[:alnum:]./]+"' # project heahders + Priority: 3 + - Regex: '' # Criterion headers + Priority: 2 + - Regex: "<[[:alnum:]./]+>" # System/Standard headers + Priority: 1 + +# Make args on multiple lines if line overflow +BinPackArguments: false +BinPackParameters: false +ExperimentalAutoDetectBinPacking: false +AllowAllParametersOfDeclarationOnNextLine: false + +# namespaces +NamespaceIndentation: All + +# switch cases +IndentCaseLabels: true + +# templates +AlwaysBreakTemplateDeclarations: true diff --git a/packages/ecs/.gitignore b/packages/ecs/.gitignore index e4b7d81..c5431c0 100644 --- a/packages/ecs/.gitignore +++ b/packages/ecs/.gitignore @@ -12,6 +12,40 @@ # Built Visual Studio Code Extensions *.vsix +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 @@ -223,9 +257,19 @@ dist .yarn/install-state.gz .pnp.* +### Private + # NX .nx/ # Compiled files src/**/*.js src/**/*.d.ts + +# pubilc directory +lib/libecs.wasm +lib/index.d.ts +lib/index.js +lib/libecs.js +compile_commands.json +emsdk/ diff --git a/packages/ecs/.idea/.gitignore b/packages/ecs/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/packages/ecs/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/packages/ecs/.idea/.name b/packages/ecs/.idea/.name new file mode 100644 index 0000000..fc60d4a --- /dev/null +++ b/packages/ecs/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine ECS \ No newline at end of file diff --git a/packages/ecs/.idea/[NanoForge] Engine ECS.iml b/packages/ecs/.idea/[NanoForge] Engine ECS.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/packages/ecs/.idea/[NanoForge] Engine ECS.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/codeStyles/Project.xml b/packages/ecs/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a57ead7 --- /dev/null +++ b/packages/ecs/.idea/codeStyles/Project.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/codeStyles/codeStyleConfig.xml b/packages/ecs/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/packages/ecs/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/editor.xml b/packages/ecs/.idea/editor.xml new file mode 100644 index 0000000..d70eddc --- /dev/null +++ b/packages/ecs/.idea/editor.xml @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/git_toolbox_blame.xml b/packages/ecs/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/packages/ecs/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/git_toolbox_prj.xml b/packages/ecs/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/packages/ecs/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/inspectionProfiles/Project_Default.xml b/packages/ecs/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..e852c49 --- /dev/null +++ b/packages/ecs/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/misc.xml b/packages/ecs/.idea/misc.xml new file mode 100644 index 0000000..7ecbce5 --- /dev/null +++ b/packages/ecs/.idea/misc.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/modules.xml b/packages/ecs/.idea/modules.xml new file mode 100644 index 0000000..942670c --- /dev/null +++ b/packages/ecs/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/prettier.xml b/packages/ecs/.idea/prettier.xml new file mode 100644 index 0000000..b0c1c68 --- /dev/null +++ b/packages/ecs/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/ecs/.idea/vcs.xml b/packages/ecs/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/packages/ecs/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/ecs/Makefile b/packages/ecs/Makefile new file mode 100644 index 0000000..ce863f6 --- /dev/null +++ b/packages/ecs/Makefile @@ -0,0 +1,64 @@ +SRC = wasm/SparseArray.cpp\ + wasm/Entity.cpp\ + wasm/Utils.cpp\ + wasm/Registry.cpp + +NAME := libecs + +OUT_DIR = lib +JS_NAME = $(OUT_DIR)/$(NAME).js +HTML_NAME = $(OUT_DIR)/$(NAME).html +WASM_NAME = $(OUT_DIR)/$(NAME).wasm +TS_NAME = $(NAME).d.ts + +CFLAGS = -std=c++20 +LDFLAGS = -O3 --no-entry --bind -sNO_DISABLE_EXCEPTION_CATCHING -sEXPORT_EXCEPTION_HANDLING_HELPERS + +CC = em++ + +OBJ = $(SRC:.cpp=.o) + +%.o: %.cpp + $(CC) -c $< -o $@ $(CFLAGS) + +all: $(TS_NAME) + +js: $(JS_NAME) + +html: $(HTML_NAME) + +ts: $(TS_NAME) + +$(WASM_NAME): $(OBJ) + @mkdir -p $(OUT_DIR) + $(CC) $(OBJ) $(LDFLAGS) -o $(WASM_NAME) + +$(JS_NAME): LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s STANDALONE_WASM=1 +$(JS_NAME): $(OBJ) + @mkdir -p $(OUT_DIR) + $(CC) $(OBJ) $(LDFLAGS) -o $(JS_NAME) + +$(HTML_NAME): LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s STANDALONE_WASM=1 +$(HTML_NAME): $(OBJ) + @mkdir -p $(OUT_DIR) + $(CC) $(OBJ) $(LDFLAGS) -o $(HTML_NAME) + +$(TS_NAME): LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s ENVIRONMENT=web +$(TS_NAME): $(OBJ) + @mkdir -p $(OUT_DIR) + $(CC) $(OBJ) $(LDFLAGS) --emit-tsd $(TS_NAME) -o $(JS_NAME) + +clean: + $(RM) $(OBJ) + $(RM) $(JS_NAME) $(WASM_NAME) $(HTML_NAME) $(TS_NAME) + +fclean: clean + +tests: LDFLAGS += -s MODULARIZE=1 +tests: $(OBJ) + @mkdir -p $(OUT_DIR) + $(CC) $(OBJ) $(LDFLAGS) --emit-tsd $(TS_NAME) -o $(JS_NAME) + +re: fclean all + +.PHONY: re fclean all clean tests diff --git a/packages/ecs/README.md b/packages/ecs/README.md index 8680ad6..8b72baf 100644 --- a/packages/ecs/README.md +++ b/packages/ecs/README.md @@ -1 +1,13 @@ # Engine Core + +To install emsdk the WASM compiler we are using run : + +```sh +git clone https://github.com/emscripten-core/emsdk.git +cd emsdk/ +./emsdk install latest +./emsdk activate latest +source "$PWD/emsdk_env.sh" +echo -ne "export EMSDK_QUIET=1\nsource \"$PWD/emsdk_env.sh\"\n" >> ~/.bashrc +cd .. +``` diff --git a/packages/ecs/eslint.config.js b/packages/ecs/eslint.config.js index a6a38b9..4a7529e 100644 --- a/packages/ecs/eslint.config.js +++ b/packages/ecs/eslint.config.js @@ -2,16 +2,20 @@ import pluginJs from "@eslint/js"; import eslintConfigPrettier from "eslint-config-prettier"; import globals from "globals"; import tseslint from "typescript-eslint"; +import pluginJest from "eslint-plugin-jest"; export default [ - { files: ["src/**/*.{ts}"] }, + { + files: ["src/**/*.{ts}"], + }, { languageOptions: { globals: globals.node } }, + pluginJs.configs.recommended, ...tseslint.configs.recommended, ...tseslint.configs.strict, eslintConfigPrettier, - { ignores: ['**/*.js'] }, + { ignores: ["**/*.js"] }, { rules: { "@typescript-eslint/consistent-type-imports": [ @@ -42,4 +46,18 @@ export default [ ], }, }, + { + files: ["**/*.spec.ts"], + plugins: { jest: pluginJest }, + languageOptions: { + globals: pluginJest.environments.globals.globals, + }, + rules: { + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + } + } ]; diff --git a/packages/ecs/jest.config.json b/packages/ecs/jest.config.json new file mode 100644 index 0000000..b75e6b6 --- /dev/null +++ b/packages/ecs/jest.config.json @@ -0,0 +1,12 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": "test", + "collectCoverageFrom": ["**/*.(t|j)s"], + "testEnvironment": "node", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "verbose": true, + "testTimeout": 5000 +} diff --git a/packages/ecs/lib/index.ts b/packages/ecs/lib/index.ts new file mode 100644 index 0000000..acde6e2 --- /dev/null +++ b/packages/ecs/lib/index.ts @@ -0,0 +1,2 @@ +export * from "./libecs"; +export { default as Module } from "./libecs"; diff --git a/packages/ecs/lib/libecs.d.ts b/packages/ecs/lib/libecs.d.ts new file mode 100644 index 0000000..6839d53 --- /dev/null +++ b/packages/ecs/lib/libecs.d.ts @@ -0,0 +1,89 @@ +// TypeScript bindings for emscripten-generated code. Automatically generated at compile time. +declare namespace RuntimeExports { + let HEAPF32: any; + let HEAPF64: any; + let HEAP_DATA_VIEW: any; + let HEAP8: any; + let HEAPU8: any; + let HEAP16: any; + let HEAPU16: any; + let HEAP32: any; + let HEAPU32: any; + let HEAP64: any; + let HEAPU64: any; +} +interface WasmModule { +} + +export interface ClassHandle { + isAliasOf(other: ClassHandle): boolean; + delete(): void; + deleteLater(): this; + isDeleted(): boolean; + clone(): this; +} +export interface container extends ClassHandle { + size(): number; + get(_0: number): any | undefined | undefined; + push_back(_0?: any): void; + resize(_0: number, _1?: any): void; + set(_0: number, _1?: any): boolean; +} + +export interface SparseArray extends ClassHandle { + setByCopy(_0: SparseArray): SparseArray; + setByMove(_0: SparseArray): SparseArray; + clear(): void; + empty(): boolean; + erase(_0: number): void; + size(): number; + resize(_0: number): void; + getIndex(_0?: any): number; + getConst(_0: number): any | undefined; + get(_0: number): any | undefined; + insertAt(_0: number, _1?: any): any | undefined; + insertAt(_0: number, _1?: any): any | undefined; + set(_0: number, _1?: any): void; +} + +export interface Entity extends ClassHandle { + getId(): number; +} + +export interface Registry extends ClassHandle { + registerComponent(_0: {name: string, [key: string]: any}): SparseArray; + getComponentsConst(_0: {name: string, [key: string]: any}): SparseArray; + getComponents(_0: {name: string, [key: string]: any}): SparseArray; + spawnEntity(): Entity; + killEntity(_0: Entity): void; + clearEntities(): void; + removeComponent(_0: Entity, _1: {name: string, [key: string]: any}): void; + addSystem(_0: (registry: Registry) => void): void; + runSystems(): void; + clearSystems(): void; + entityFromIndex(_0: number): Entity; + removeSystem(_0: number): void; + maxEntities(): number; + getEntityComponentConst(_0: Entity, _1: {name: string, [key: string]: any}): any | undefined; + getEntityComponent(_0: Entity, _1: {name: string, [key: string]: any}): any | undefined; + addComponent(_0: Entity, _1: {name: string, [key: string]: any}): any | undefined; + getZipper(_0: any): any; +} + +interface EmbindModule { + container: { + new(): container; + }; + SparseArray: { + new(): SparseArray; + }; + Entity: { + new(_0: number): Entity; + }; + Registry: { + new(): Registry; + }; +} + +export type MainModule = WasmModule & typeof RuntimeExports & EmbindModule; +export default function MainModuleFactory (options?: unknown): Promise; diff --git a/packages/ecs/package.json b/packages/ecs/package.json index 2ce6f3d..78e749d 100644 --- a/packages/ecs/package.json +++ b/packages/ecs/package.json @@ -22,14 +22,19 @@ "directory": "packages/ecs" }, "scripts": { - "build": "tsc -b .", - "clean": "pnpm clean:types && pnpm clean:scripts && rm -f tsconfig.build.tsbuildinfo", + "build": "pnpm build:wasm && pnpm build:script", + "build:script": "tsc -b .", + "build:wasm": "make re", + "clean": "pnpm clean:wasm && pnpm clean:script", + "clean:script": "pnpm clean:types && pnpm clean:scripts && rm -f tsconfig.build.tsbuildinfo", + "clean:wasm": "make fclean", "clean:types": "find src -name '*.d.ts' -delete", "clean:scripts": "find src -name '*.js' -delete", "lint": "eslint . && prettier --check .", "fix": "eslint . --fix && prettier --write .", "taze": "taze major -w", - "lint-staged": "lint-staged" + "lint-staged": "lint-staged", + "test:unit": "make fclean && make tests -j 16 && pnpm clean:script && pnpm build:script && jest --config ./jest.config.json" }, "dependencies": { "@nanoforge/common": "workspace:^" @@ -39,13 +44,19 @@ "@commitlint/config-conventional": "^19.8.0", "@eslint/js": "^9.22.0", "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/jest": "^29.5.14", + "@types/node": "^22.13.10", "eslint": "^9.22.0", "eslint-config-prettier": "^10.1.1", "eslint-plugin-format": "^1.0.1", + "eslint-plugin-jest": "^28.11.0", "eslint-plugin-prettier": "^5.2.3", "globals": "^16.0.0", + "jest": "^29.7.0", "lint-staged": "^15.4.3", "prettier": "^3.5.3", + "ts-jest": "^29.2.6", + "typescript": "^5.8.2", "typescript-eslint": "^8.26.0" }, "engines": { diff --git a/packages/ecs/public/libecs.d.ts b/packages/ecs/public/libecs.d.ts new file mode 100644 index 0000000..365c1c4 --- /dev/null +++ b/packages/ecs/public/libecs.d.ts @@ -0,0 +1,23 @@ +// TypeScript bindings for emscripten-generated code. Automatically generated at compile time. +declare namespace RuntimeExports { + let HEAPF32: any; + let HEAPF64: any; + let HEAP_DATA_VIEW: any; + let HEAP8: any; + let HEAPU8: any; + let HEAP16: any; + let HEAPU16: any; + let HEAP32: any; + let HEAPU32: any; + let HEAP64: any; + let HEAPU64: any; +} +interface WasmModule { + __initialize(): void; +} + +interface EmbindModule { +} + +export type MainModule = WasmModule & typeof RuntimeExports & EmbindModule; +export default function MainModuleFactory (options?: unknown): Promise; diff --git a/packages/ecs/public/libecs.js b/packages/ecs/public/libecs.js new file mode 100644 index 0000000..3735e26 --- /dev/null +++ b/packages/ecs/public/libecs.js @@ -0,0 +1,15 @@ +var Module = (() => { + var _scriptName = import.meta.url; + + return ( +async function(moduleArg = {}) { + var moduleRtn; + +var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof WorkerGlobalScope!="undefined";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&process.type!="renderer";if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("module");var require=createRequire(import.meta.url)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(!import.meta.url.startsWith("data:")){scriptDirectory=nodePath.dirname(require("url").fileURLToPath(import.meta.url))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.slice(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;var runtimeInitialized=false;var isFileURI=filename=>filename.startsWith("file://");function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true}function preMain(){}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("libecs.wasm")}return new URL("libecs.wasm",import.meta.url).href}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["memory"];updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(mod,inst)=>{receiveInstance(mod,inst);resolve(mod.exports)})})}wasmBinaryFile??=findWasmBinary();try{var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}catch(e){readyPromiseReject(e);return Promise.reject(e)}}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.unshift(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.unshift(cb);var noExitRuntime=Module["noExitRuntime"]||true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(ptr);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}throw exceptionLast};var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};var embind_init_charCodes=()=>{var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes};var embind_charCodes;var readLatin1String=ptr=>{var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret};var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var BindingError;var throwBindingError=message=>{throw new BindingError(message)};var InternalError;var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=readLatin1String(name);var isUnsignedType=name.indexOf("u")!=-1;if(isUnsignedType){maxRange=(1n<<64n)-1n}registerType(primitiveType,{name,fromWireType:value=>value,toWireType:function(destructors,value){if(typeof value!="bigint"&&typeof value!="number"){throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${this.name}`)}if(typeof value=="number"){value=BigInt(value)}return value},argPackAdvance:GenericWireTypeSize,readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var GenericWireTypeSize=8;var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=readLatin1String(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},argPackAdvance:GenericWireTypeSize,readValueFromPointer:function(pointer){return this["fromWireType"](HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var finalizationRegistry=false;var detachFinalizer=handle=>{};var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var registeredPointers={};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var attachFinalizer=handle=>{if("undefined"===typeof FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{Object.assign(ClassHandle.prototype,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}})};function ClassHandle(){}var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function readPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction)=>{signature=readLatin1String(signature);function makeDynCaller(){return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};var extendError=(baseErrorType,errorName)=>{var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass};var UnboundTypeError;var getTypeName=type=>{var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv};var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError("Use 'new' to construct "+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+" has no accessible constructor")}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};var heap32VectorToArray=(count,firstElement)=>{var array=[];for(var i=0;i>2])}return array};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function usesDestructorStack(argTypes){for(var i=1;i{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var emval_freelist=[];var emval_handles=[];var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var count_emval_handles=()=>emval_handles.length/2-5-emval_freelist.length;var init_emval=()=>{emval_handles.push(0,1,undefined,1,null,1,true,1,false,1);Module["count_emval_handles"]=count_emval_handles};var Emval={toValue:handle=>{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 8:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=readLatin1String(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,argPackAdvance:GenericWireTypeSize,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name,fromWireType,toWireType,argPackAdvance:GenericWireTypeSize,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name,fromWireType:decodeMemoryView,argPackAdvance:GenericWireTypeSize,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var __embind_register_std_string=(rawType,name)=>{name=readLatin1String(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i{var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead)=>{var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=readLatin1String(name);var decodeString,encodeString,readCharAt,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;readCharAt=pointer=>HEAPU16[pointer>>1]}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;readCharAt=pointer=>HEAPU32[pointer>>2]}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||readCharAt(currentBytePtr)==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_void=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{isVoid:true,name,argPackAdvance:0,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var emval_returnValue=(returnType,destructorsRef,handle)=>{var destructors=[];var result=returnType["toWireType"](destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var __emval_as=(handle,returnType,destructorsRef)=>{handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");return emval_returnValue(returnType,destructorsRef,handle)};var emval_methodCallers=[];var __emval_call=(caller,handle,destructorsRef,args)=>{caller=emval_methodCallers[caller];handle=Emval.toValue(handle);return caller(null,handle,destructorsRef,args)};var __emval_equals=(first,second)=>{first=Emval.toValue(first);second=Emval.toValue(second);return first==second};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol};var emval_get_global=()=>{if(typeof globalThis=="object"){return globalThis}return function(){return Function}()("return this")()};var __emval_get_global=name=>{if(name===0){return Emval.toHandle(emval_get_global())}else{name=getStringOrSymbol(name);return Emval.toHandle(emval_get_global()[name])}};var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],"parameter "+i)}return a};var reflectConstruct=Reflect.construct;var __emval_get_method_caller=(argCount,argTypes,kind)=>{var types=emval_lookupTypes(argCount,argTypes);var retType=types.shift();argCount--;var functionBody=`return function (obj, func, destructorsRef, args) {\n`;var offset=0;var argsList=[];if(kind===0){argsList.push("obj")}var params=["retType"];var args=[retType];for(var i=0;it.name).join(", ")}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_get_property=(handle,key)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])};var __emval_incref=handle=>{if(handle>9){emval_handles[handle+1]+=1}};var __emval_instanceof=(object,constructor)=>{object=Emval.toValue(object);constructor=Emval.toValue(constructor);return object instanceof constructor};var __emval_is_string=handle=>{handle=Emval.toValue(handle);return typeof handle=="string"};var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var __emval_take_value=(type,arg)=>{type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](arg);return Emval.toHandle(v)};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var incrementExceptionRefcount=ptr=>___cxa_increment_exception_refcount(ptr);Module["incrementExceptionRefcount"]=incrementExceptionRefcount;var decrementExceptionRefcount=ptr=>___cxa_decrement_exception_refcount(ptr);Module["decrementExceptionRefcount"]=decrementExceptionRefcount;var stackAlloc=sz=>__emscripten_stack_alloc(sz);var getExceptionMessageCommon=ptr=>{var sp=stackSave();var type_addr_addr=stackAlloc(4);var message_addr_addr=stackAlloc(4);___get_exception_message(ptr,type_addr_addr,message_addr_addr);var type_addr=HEAPU32[type_addr_addr>>2];var message_addr=HEAPU32[message_addr_addr>>2];var type=UTF8ToString(type_addr);_free(type_addr);var message;if(message_addr){message=UTF8ToString(message_addr);_free(message_addr)}stackRestore(sp);return[type,message]};var getExceptionMessage=ptr=>getExceptionMessageCommon(ptr);Module["getExceptionMessage"]=getExceptionMessage;embind_init_charCodes();BindingError=Module["BindingError"]=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};InternalError=Module["InternalError"]=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};init_ClassHandle();init_RegisteredPointer();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var wasmImports={__cxa_begin_catch:___cxa_begin_catch,__cxa_find_matching_catch_2:___cxa_find_matching_catch_2,__cxa_find_matching_catch_3:___cxa_find_matching_catch_3,__cxa_throw:___cxa_throw,__resumeException:___resumeException,_embind_register_bigint:__embind_register_bigint,_embind_register_bool:__embind_register_bool,_embind_register_class:__embind_register_class,_embind_register_class_constructor:__embind_register_class_constructor,_embind_register_class_function:__embind_register_class_function,_embind_register_emval:__embind_register_emval,_embind_register_float:__embind_register_float,_embind_register_integer:__embind_register_integer,_embind_register_memory_view:__embind_register_memory_view,_embind_register_optional:__embind_register_optional,_embind_register_std_string:__embind_register_std_string,_embind_register_std_wstring:__embind_register_std_wstring,_embind_register_void:__embind_register_void,_emval_as:__emval_as,_emval_call:__emval_call,_emval_decref:__emval_decref,_emval_equals:__emval_equals,_emval_get_global:__emval_get_global,_emval_get_method_caller:__emval_get_method_caller,_emval_get_property:__emval_get_property,_emval_incref:__emval_incref,_emval_instanceof:__emval_instanceof,_emval_is_string:__emval_is_string,_emval_new_cstring:__emval_new_cstring,_emval_new_object:__emval_new_object,_emval_run_destructors:__emval_run_destructors,_emval_set_property:__emval_set_property,_emval_take_value:__emval_take_value,invoke_ii,invoke_iii,invoke_v,invoke_vii,invoke_viii};var wasmExports=await createWasm();var _malloc=wasmExports["malloc"];var ___getTypeName=wasmExports["__getTypeName"];var __initialize=Module["__initialize"]=wasmExports["_initialize"];var _free=wasmExports["free"];var _setThrew=wasmExports["setThrew"];var __emscripten_tempret_set=wasmExports["_emscripten_tempret_set"];var __emscripten_stack_restore=wasmExports["_emscripten_stack_restore"];var __emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"];var _emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"];var ___cxa_increment_exception_refcount=wasmExports["__cxa_increment_exception_refcount"];var ___cxa_decrement_exception_refcount=wasmExports["__cxa_decrement_exception_refcount"];var ___get_exception_message=wasmExports["__get_exception_message"];var ___cxa_can_catch=wasmExports["__cxa_can_catch"];var ___cxa_get_exception_ptr=wasmExports["__cxa_get_exception_ptr"];function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}var mainArgs=undefined;function callMain(args=[]){var entryFunction=__initialize;mainArgs=[thisProgram].concat(args);try{entryFunction();var ret=0;exitJS(ret,true);return ret}catch(e){return handleException(e)}}function run(args=arguments_){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();var noInitialRun=Module["noInitialRun"];if(!noInitialRun)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise; + + + return moduleRtn; +} +); +})(); +export default Module; diff --git a/packages/ecs/public/libecs.wasm b/packages/ecs/public/libecs.wasm new file mode 100755 index 0000000..f8f430b Binary files /dev/null and b/packages/ecs/public/libecs.wasm differ diff --git a/packages/ecs/src/ecs-library.ts b/packages/ecs/src/ecs-library.ts index 3f43903..f38588c 100644 --- a/packages/ecs/src/ecs-library.ts +++ b/packages/ecs/src/ecs-library.ts @@ -1,3 +1,98 @@ -import { type ILibrary } from "@nanoforge/common"; +import { type AssetManagerLibrary } from "@nanoforge/asset-manager"; +import { BaseComponentSystemLibrary, type InitContext } from "@nanoforge/common"; -export class ECSLibrary implements ILibrary {} +import type { Entity, MainModule, Registry, SparseArray } from "../lib"; +import { Module } from "../lib"; + +export type Component = { name: string; [key: string]: any }; +export type System = (registry: Registry) => void; + +export class ECSLibrary extends BaseComponentSystemLibrary { + private module: MainModule; + private registry: Registry; + private readonly path: string = "libecs.wasm"; + + get name(): string { + return "ECSLibrary"; + } + + async init(context: InitContext): Promise { + const wasmFile = await context.libraries + .getAssetManager() + .library.getWasm(this.path); + this.module = await Module({ locateFile: () => wasmFile.path }); + this.registry = new this.module.Registry(); + } + + async run(): Promise { + this.runSystems(); + } + + clear(): Promise { + return Promise.resolve(); + } + + addComponent(entity: Entity, component: Component): void { + this.registry.addComponent(entity, component); + } + + createEntity(): Entity { + return this.registry.spawnEntity(); + } + + getComponents(component: Component): SparseArray { + return this.registry.getComponents(component); + } + + removeComponent(entity: Entity, component: Component): void { + this.registry.removeComponent(entity, component); + } + + getEntityComponent(entity: Entity, component: Component): Component | undefined { + return this.registry.getEntityComponent(entity, component); + } + + getEntityComponentConst(entity: Entity, component: Component): Component | undefined { + return this.registry.getEntityComponentConst(entity, component); + } + + clearEntities(): void { + this.registry.clearEntities(); + } + + runSystems(): void { + this.registry.runSystems(); + } + + clearSystems(): void { + this.registry.clearSystems(); + } + + removeSystem(system: any): void { + this.registry.removeSystem(system); + } + + registerComponent(component: any): SparseArray { + return this.registry.registerComponent(component); + } + + entityFromIndex(index: number): Entity { + return this.registry.entityFromIndex(index); + } + + killEntity(entity: Entity): void { + this.registry.killEntity(entity); + } + + maxEntities(): number { + return this.registry.maxEntities(); + } + + addSystem(system: System): void { + this.registry.addSystem(system); + } + + getZipper(types: [Component]): [any] { + return this.registry.getZipper(types); + } +} diff --git a/packages/ecs/src/index.ts b/packages/ecs/src/index.ts index e69de29..bdc631f 100644 --- a/packages/ecs/src/index.ts +++ b/packages/ecs/src/index.ts @@ -0,0 +1,3 @@ +import "../lib/libecs.wasm"; + +export * from "./ecs-library"; diff --git a/packages/ecs/test/ecs-library.spec.ts b/packages/ecs/test/ecs-library.spec.ts new file mode 100644 index 0000000..daf7b53 --- /dev/null +++ b/packages/ecs/test/ecs-library.spec.ts @@ -0,0 +1,60 @@ +import { AssetManagerLibrary } from "@nanoforge/asset-manager"; +import { ApplicationContext, InitContext } from "@nanoforge/common"; +import { EditableLibraryManager } from "@nanoforge/core/src/common/library/manager/library.manager"; +import { ECSLibrary } from "@nanoforge/ecs/src/ecs-library"; + +class Position { + name: string = "Position"; + constructor( + public x: number, + public y: number, + ) { + this.x = x; + this.y = y; + } +} + +describe("ECSLibrary", () => { + let ecs: ECSLibrary; + const assetManager = new AssetManagerLibrary(); + const appContext = new ApplicationContext(); + const libraryManager = new EditableLibraryManager(); + const context = new InitContext(appContext, libraryManager, { + // @ts-ignore + canvas: null, + files: { + assets: new Map(), + wasm: new Map([["/libecs.wasm", "./lib/libecs.wasm"]]), + wgsl: new Map(), + }, + }); + libraryManager.setAssetManager(assetManager); + + beforeAll(async () => { + await assetManager.init(context); + }); + + beforeEach(async () => { + ecs = new ECSLibrary(); + await ecs.init(context); + }); + + test("init and spawn entity", async () => { + const entity = ecs.createEntity(); + expect(entity).toBeDefined(); + expect(entity.getId()).toBe(0); + }); + + test("add component to entity", async () => { + const entity = ecs.createEntity(); + const pos = new Position(1, 2); + ecs.addComponent(entity, pos); + const components = ecs.getComponents(Position); + expect(components.get(entity.getId())).toStrictEqual(new Position(1, 2)); + expect(components.size()).toBe(1); + }); + + test("clear", async () => { + await ecs.clear(); + }); +}); diff --git a/packages/ecs/test/tsconfig.json b/packages/ecs/test/tsconfig.json new file mode 100644 index 0000000..399ab33 --- /dev/null +++ b/packages/ecs/test/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.spec.json", + "compilerOptions": { + "paths": { + "@nanoforge/common": ["./packages/common"], + "@nanoforge/core": ["./packages/core"], + "@nanoforge/core/*": ["./packages/core/*"], + "@nanoforge/asset-manager": ["./packages/asset-manager"], + "@nanoforge/ecs": ["./packages/ecs"], + "@nanoforge/ecs/*": ["./packages/ecs/*"], + "@nanoforge/graphics-2d": ["./packages/graphics-2d"] + } + } +} diff --git a/packages/ecs/test/wasm/Registry.spec.ts b/packages/ecs/test/wasm/Registry.spec.ts new file mode 100644 index 0000000..a5edffa --- /dev/null +++ b/packages/ecs/test/wasm/Registry.spec.ts @@ -0,0 +1,187 @@ +import Module from "../../lib/libecs.js"; + +class Velocity { + name: string = "Velocity"; + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +class Position { + name: string = "Position"; + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +describe("Registry", () => { + test("1 entity 2 components", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + const vel = new Velocity(1, 2); + const pos = new Position(4, 5); + + const e = r.spawnEntity(); + expect(e.getId()).toBe(0); + + r.addComponent(e, vel); + r.addComponent(e, pos); + + const velocities = r.getComponents(Velocity); + const positions = r.getComponents(Position); + + expect(velocities.get(e.getId())).toStrictEqual(new Velocity(1, 2)); + expect(positions.get(e.getId())).toStrictEqual(new Position(4, 5)); + }); + + test("override components", async () => { + const m = await Module(); + const r = new m.Registry(); + + const vel = new Velocity(1, 2); + const vel2 = new Velocity(4, 5); + + const e = r.spawnEntity(); + + r.addComponent(e, vel); + expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(1, 2)); + + r.addComponent(e, vel2); + expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(4, 5)); + }); + + test("basic remove", async () => { + const m = await Module(); + const r = new m.Registry(); + + const vel = new Velocity(1, 2); + const e = r.spawnEntity(); + + r.addComponent(e, vel); + expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(1, 2)); + + r.removeComponent(e, Velocity); + expect(r.getComponents(Velocity).size()).toEqual(1); + expect(r.getComponents(Velocity).get(e.getId())).toBeUndefined(); + }); + + test("basic kill", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + const vel = new Velocity(1, 2); + const pos = new Position(4, 5); + + r.spawnEntity(); + const e = r.spawnEntity(); + expect(e.getId()).toBe(1); + + r.addComponent(e, vel); + r.addComponent(e, pos); + + const velocities = r.getComponents(Velocity); + const positions = r.getComponents(Position); + + expect(positions.size()).toEqual(2); + expect(velocities.get(e.getId())).toStrictEqual(new Velocity(1, 2)); + expect(positions.get(e.getId())).toStrictEqual(new Position(4, 5)); + + r.killEntity(e); + expect(r.getComponents(Velocity).get(e.getId())).toBeUndefined(); + expect(r.getComponents(Position).get(e.getId())).toBeUndefined(); + }); + + test("system incrementing a variable", async () => { + const m = await Module(); + const r = new m.Registry(); + + let counter = 0; + + r.addSystem(() => { + counter += 1; + }); + + for (let i = 0; i <= 15; i++) { + expect(counter).toBe(i); + r.runSystems(); + } + expect(counter).toBe(16); + }); + + test("system incrementing component positions by velocity", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + const e = r.spawnEntity(); + const e2 = r.spawnEntity(); + expect(e2.getId()).toBe(1); + const e3 = r.spawnEntity(); + + r.addComponent(e, new Velocity(1, 1)); + r.addComponent(e, new Position(-2, -2)); + + r.addComponent(e2, new Velocity(-1, -1)); + r.addComponent(e2, new Position(2, 2)); + + r.addComponent(e3, new Position(0, 0)); + + r.addSystem(() => { + const velocities = r.getComponents(Velocity); + const positions = r.getComponents(Position); + for (let i = 0; i < velocities.size() && i < positions.size(); i++) { + if (velocities.get(i) === undefined || positions.get(i) === undefined) { + continue; + } + positions.get(i).x += velocities.get(i).x; + positions.get(i).y += velocities.get(i).y; + } + }); + + expect(r.getComponents(Position).size()).toEqual(3); + + expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(-2, -2)); + expect(r.getComponents(Position).get(e2.getId())).toStrictEqual(new Position(2, 2)); + expect(r.getComponents(Position).get(e3.getId())).toStrictEqual(new Position(0, 0)); + r.runSystems(); + + expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(-1, -1)); + expect(r.getComponents(Position).get(e2.getId())).toStrictEqual(new Position(1, 1)); + expect(r.getComponents(Position).get(e3.getId())).toStrictEqual(new Position(0, 0)); + r.runSystems(); + + expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(0, 0)); + expect(r.getComponents(Position).get(e2.getId())).toStrictEqual(new Position(0, 0)); + expect(r.getComponents(Position).get(e3.getId())).toStrictEqual(new Position(0, 0)); + }); + + test("Try unallowed component name", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + const entityComp = { name: "entity" }; + + const e = r.spawnEntity(); + expect(e.getId()).toBe(0); + + try { + r.addComponent(e, entityComp); + fail(); + } catch (e) { + //@ts-ignore + expect(m.getExceptionMessage(e)[1].toString()).toBeDefined(); + } + }); +}); diff --git a/packages/ecs/test/wasm/SparseArray.spec.ts b/packages/ecs/test/wasm/SparseArray.spec.ts new file mode 100644 index 0000000..1b1093d --- /dev/null +++ b/packages/ecs/test/wasm/SparseArray.spec.ts @@ -0,0 +1,40 @@ +import Module from "../../lib/libecs.js"; + +describe("SparseArray", () => { + test("basic instantation", async () => { + const m = await Module(); + const sa = new m.SparseArray(); + expect(sa).toBeDefined(); + expect(sa.size()).toBe(0); + }); + + test("basic insert", async () => { + const m = await Module(); + const sa = new m.SparseArray(); + sa.set(0, 1); + expect(sa.size()).toBe(1); + expect(sa.get(0)).toBe(1); + }); + + test("basic remove", async () => { + const m = await Module(); + const sa = new m.SparseArray(); + sa.set(0, 1); + sa.erase(0); + expect(sa.size()).toBe(1); + expect(sa.get(0)).toBe(undefined); + }); + + test("basic iteration with get and size", async () => { + const m = await Module(); + const sa = new m.SparseArray(); + sa.set(0, 1); + sa.set(1, 2); + sa.set(2, 3); + let sum = 0; + for (let i = 0; i < sa.size(); i++) { + sum += sa.get(i); + } + expect(sum).toBe(6); + }); +}); diff --git a/packages/ecs/test/wasm/Zipper.spec.ts b/packages/ecs/test/wasm/Zipper.spec.ts new file mode 100644 index 0000000..f200b1f --- /dev/null +++ b/packages/ecs/test/wasm/Zipper.spec.ts @@ -0,0 +1,123 @@ +import Module from "../../lib/libecs.js"; + +class Velocity { + name: string = "Velocity"; + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +class Position { + name: string = "Position"; + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +describe("Zipper", () => { + test("single simple sparse array instantation", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + for (let i = 0; i < 5; i++) { + const e = r.spawnEntity(); + r.addComponent(e, new Velocity(i, i)); + } + + const zip = r.getZipper([Velocity]); + + expect(zip).toBeDefined(); + expect(zip).toStrictEqual([ + { Velocity: new Velocity(0, 0) }, + { Velocity: new Velocity(1, 1) }, + { Velocity: new Velocity(2, 2) }, + { Velocity: new Velocity(3, 3) }, + { Velocity: new Velocity(4, 4) }, + ]); + }); + + test("single complex sparse array instantation", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + for (let i = 0; i < 5; i++) { + const e = new m.Entity(i * 5); + r.addComponent(e, new Velocity(i, i)); + } + + const zip = r.getZipper([Velocity]); + expect(zip).toBeDefined(); + + expect(zip[0]).toStrictEqual({ Velocity: new Velocity(0, 0) }); + expect(zip[5]).toStrictEqual({ Velocity: new Velocity(1, 1) }); + expect(zip[10]).toStrictEqual({ Velocity: new Velocity(2, 2) }); + expect(zip[15]).toStrictEqual({ Velocity: new Velocity(3, 3) }); + expect(zip[20]).toStrictEqual({ Velocity: new Velocity(4, 4) }); + }); + + test("multiple complex sparse array instantation", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + for (let i = 0; i < 20; i++) { + const e = r.spawnEntity(); + if (i % 5 === 0) r.addComponent(e, new Velocity(0, i)); + if (i % 3 === 0) r.addComponent(e, new Position(i, 0)); + } + + const zip = r.getZipper([Velocity, Position]); + expect(zip).toBeDefined(); + + for (let i = 0; i < 20; i++) { + if (i % 3 === 0 && i % 5 === 0) { + expect(zip[i]).toStrictEqual({ + Velocity: new Velocity(0, i), + Position: new Position(i, 0), + }); + } + } + }); + + test("simple indexed zipper modification", async () => { + const m = await Module(); + const r = new m.Registry(); + expect(r).toBeDefined(); + + for (let i = 0; i < 20; i++) { + const e = r.spawnEntity(); + if (i % 5 === 0) { + r.addComponent(e, new Velocity(0, i)); + } + } + + let zip = r.getZipper([Velocity]); + expect(zip).toBeDefined(); + + for (let i = 0; i < 20; i++) { + if (i % 5 === 0) { + const vel = zip[i]["Velocity"]; + vel.y *= 2; + } + } + + zip = r.getZipper([Velocity]); + for (let i = 0; i < 20; i++) { + if (i % 5 === 0) { + expect(zip[i]).toStrictEqual({ + Velocity: new Velocity(0, i * 2), + }); + } + } + }); +}); diff --git a/packages/ecs/tsconfig.build.json b/packages/ecs/tsconfig.build.json index 2e31798..03fe868 100644 --- a/packages/ecs/tsconfig.build.json +++ b/packages/ecs/tsconfig.build.json @@ -4,14 +4,18 @@ "outDir": ".", "rootDir": ".", "paths": { + "@lib": ["./lib"], "@nanoforge/common": ["../common"], - "@nanoforge/common/*": ["../common/*"] + "@nanoforge/asset-manager": ["../asset-manager"] } }, "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], "references": [ { "path": "../common/tsconfig.build.json" + }, + { + "path": "../asset-manager/tsconfig.build.json" } ] } diff --git a/packages/ecs/tsconfig.json b/packages/ecs/tsconfig.json index 2ae9e3c..a74c8e2 100644 --- a/packages/ecs/tsconfig.json +++ b/packages/ecs/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../tsconfig.build.json", "compilerOptions": { - "types": ["node"] + "types": ["jest", "node"] }, "files": [], "include": [], diff --git a/packages/ecs/wasm/Entity.cpp b/packages/ecs/wasm/Entity.cpp new file mode 100644 index 0000000..30064bb --- /dev/null +++ b/packages/ecs/wasm/Entity.cpp @@ -0,0 +1,23 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#include + +#include "Entity.hpp" + +namespace nfo { + EMSCRIPTEN_BINDINGS(Entity) + { + emscripten::class_("Entity").constructor().function("getId", &Entity::get_id); + } +} // namespace nfo diff --git a/packages/ecs/wasm/Entity.hpp b/packages/ecs/wasm/Entity.hpp new file mode 100644 index 0000000..ddc0381 --- /dev/null +++ b/packages/ecs/wasm/Entity.hpp @@ -0,0 +1,36 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#pragma once + +#include + +namespace nfo { + class Entity { + public: + explicit Entity(const std::size_t id) : _id(id) {} + + operator std::size_t() const + { + return _id; + } + + [[nodiscard]] std::size_t get_id() const + { + return _id; + } + + private: + std::size_t _id = 0; + }; +} // namespace nfo diff --git a/packages/ecs/wasm/Registry.cpp b/packages/ecs/wasm/Registry.cpp new file mode 100644 index 0000000..25f14a1 --- /dev/null +++ b/packages/ecs/wasm/Registry.cpp @@ -0,0 +1,60 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#include +#include +#include "Utils.hpp" + +#include "Registry.hpp" + +namespace nfo { + EMSCRIPTEN_DECLARE_VAL_TYPE(System); + + EMSCRIPTEN_BINDINGS(Registry) + { + emscripten::register_type("{name: string, [key: string]: any}"); + emscripten::register_type("(registry: Registry) => void"); + + emscripten::class_("Registry") + .constructor() + .function("registerComponent", &Registry::register_component) + .function( + "getComponentsConst", + emscripten::select_overload const &(const Component &) const, Registry>(&Registry::get_components) + ) + .function("getComponents", emscripten::select_overload &(const Component &), Registry>(&Registry::get_components)) + .function( + "getEntityComponentConst", + emscripten::select_overload const &(Entity, const Component &) const, Registry>(&Registry::get_entity_component) + ) + .function( + "getEntityComponent", + emscripten::select_overload &(Entity, const Component &), Registry>(&Registry::get_entity_component) + ) + .function("spawnEntity", &Registry::spawn_entity) + .function("entityFromIndex", &Registry::entity_from_index) + .function("killEntity", &Registry::kill_entity) + .function("clearEntities", &Registry::clear_entities) + .function( + "addComponent", + emscripten::select_overload::reference_type &(const Entity &, Component &&), Registry>(&Registry::add_component) + ) + .function("removeComponent", emscripten::select_overload(&Registry::remove_component)) + .function("addSystem", emscripten::select_overload(&Registry::add_system)) + .function("runSystems", &Registry::run_systems) + .function("removeSystem", &Registry::remove_system) + .function("clearSystems", &Registry::clear_systems) + .function("getZipper", &Registry::get_zipper) + .function("maxEntities", &Registry::max_entities); + } +} // namespace nfo diff --git a/packages/ecs/wasm/Registry.hpp b/packages/ecs/wasm/Registry.hpp new file mode 100644 index 0000000..d025302 --- /dev/null +++ b/packages/ecs/wasm/Registry.hpp @@ -0,0 +1,222 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Entity.hpp" +#include "SparseArray.hpp" +#include "Utils.hpp" + +namespace nfo { + class Registry { + public: + SparseArray ®ister_component(const Component &c) + { + std::string component_type(get_js_class_name(c)); + if (component_type == "entity" || component_type == "id") + throw std::runtime_error("Component type '" + component_type + "' not supported : you can't use : id, entity, " + UNKNOWN_COMPONENT_TYPE); + if (!_components_arrays.contains(component_type)) + _components_arrays.emplace(component_type, SparseArray()); + if (!_remove_functions.contains(component_type)) { + _remove_functions.emplace(component_type, [c](Registry ®, Entity const &ent) { + SparseArray &array = reg.get_components(c); + array.erase(ent); + }); + } + // TODO: rework logger + // if (!_loggers.contains(component_type)) { + // _loggers.emplace(component_type, [](Registry const ®, Entity const &ent) { + // const auto &array = reg.get_components(); + // const std::optional &comp = array[ent]; + // if (comp.has_value()) + // comp.value().log(); + // return comp.has_value(); + // }); + // } + return std::any_cast &>(_components_arrays[component_type]); + } + + SparseArray &get_components(const Component &c) + { + const std::string component_type(get_js_class_name(c)); + if (!_components_arrays.contains(component_type)) + register_component(c); + std::any &components = _components_arrays[component_type]; + return std::any_cast &>(components); + } + + [[nodiscard]] SparseArray const &get_components(const Component &c) const + { + const std::string component_type(get_js_class_name(c)); + if (!_components_arrays.contains(component_type)) + throw std::runtime_error(component_type + " array not registered"); + const std::any &components = _components_arrays.find(component_type)->second; + return std::any_cast &>(components); + } + + std::optional &get_entity_component(const Entity e, const Component &c) + { + const std::string component_type(get_js_class_name(c)); + if (!_components_arrays.contains(component_type)) + register_component(c); + std::any &components = _components_arrays[component_type]; + return std::any_cast &>(components)[e]; + } + + [[nodiscard]] std::optional const &get_entity_component(const Entity e, const Component &c) const + { + const std::string component_type(get_js_class_name(c)); + if (!_components_arrays.contains(component_type)) + throw std::runtime_error(component_type + " array not registered"); + const std::any &components = _components_arrays.find(component_type)->second; + return std::any_cast &>(components)[e]; + } + + [[nodiscard]] Entity spawn_entity() + { + if (!_dead_entities.empty()) { + const Entity entity = _dead_entities.back(); + _dead_entities.pop_back(); + return entity; + } + _next_entity += 1; + return Entity(_next_entity - 1); + } + + Entity entity_from_index(const std::size_t component_type) + { + if (std::ranges::find(_dead_entities, component_type) != _dead_entities.end() || component_type >= _next_entity) + throw std::runtime_error("Entity index out of range."); + return Entity(component_type); + } + + void kill_entity(Entity const &e) + { + _dead_entities.push_back(e); + for (const std::function &remove_function : std::views::values(_remove_functions)) + remove_function(*this, e); + } + + void clear_entities() + { + _next_entity = 0; + _remove_functions.clear(); + _dead_entities.clear(); + _loggers.clear(); + _components_arrays.clear(); + } + + SparseArray::reference_type add_component(Entity const &to, Component &&c) + { + const std::string component_type(get_js_class_name(c)); + if (!_components_arrays.contains(component_type)) { + register_component(c); + } + return get_components(c).insert_at(to, c); + } + + void remove_component(Entity const &from, Component &&c) + { + const std::string component_type(get_js_class_name(c)); + if (!_components_arrays.contains(component_type)) + register_component(c); + if (_remove_functions.contains(component_type)) + _remove_functions[component_type](*this, from); + } + + template + void add_system(Function &&f) + { + _systems.emplace_back(std::forward(f)); + } + + void remove_system(const std::size_t system_idx) + { + if (system_idx >= _systems.size()) + return; + _systems.erase(_systems.begin() + static_cast(system_idx)); + } + + void clear_systems() + { + _systems.clear(); + } + + void run_systems() + { + std::vector> systems_copy = _systems; + for (std::function &system : systems_copy) + system(*this); + } + + void log(const Entity &entity) const + { + for (const auto &logger : std::views::values(_loggers)) { + if (logger(*this, entity)) + std::cout << ", "; + } + } + + [[nodiscard]] std::size_t max_entities() const + { + return _next_entity; + } + + emscripten::val get_zipper(const emscripten::val &comps) + { + if (!comps.isArray()) + throw std::runtime_error("getZipper: need an array of comps as parameter"); + + std::size_t max = SIZE_MAX; + std::map *> arrays; + for (int i = 0; i < comps["length"].as(); i++) { + SparseArray &components = get_components(Component(comps[i])); + arrays[get_js_class_name(comps[i])] = &components; + max = (std::min)(components.size(), max); + } + + emscripten::val arr = emscripten::val::array(); + for (std::size_t idx = 0; idx < max; idx++) { + emscripten::val obj = emscripten::val::object(); + bool need_to_add = true; + for (const auto &[name, sparse_array] : arrays) { + if (!(*sparse_array)[idx].has_value()) { + need_to_add = false; + break; + } + obj.set(name, (*sparse_array)[idx].value()); + } + if (need_to_add) + arr.set(idx, obj); + } + return arr; + } + + private: + std::unordered_map _components_arrays; + + std::unordered_map> _remove_functions; + std::unordered_map> _loggers; + std::vector> _systems; + + std::vector _dead_entities; + std::size_t _next_entity{0}; + }; +} // namespace nfo diff --git a/packages/ecs/wasm/SparseArray.cpp b/packages/ecs/wasm/SparseArray.cpp new file mode 100644 index 0000000..da9e1f0 --- /dev/null +++ b/packages/ecs/wasm/SparseArray.cpp @@ -0,0 +1,74 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#include +#include + +#include "SparseArray.hpp" + +namespace nfo { + EMSCRIPTEN_BINDINGS(SparseArray) + { + emscripten::register_optional(); + emscripten::register_vector>("container"); + + emscripten::class_>("SparseArray") + .constructor<>() + .function("erase", &SparseArray::erase) + .function("size", &SparseArray::size) + .function( + "getIndex", + emscripten::select_overload::size_type(SparseArray::const_reference_type) const>( + &SparseArray::get_index + ) + ) + .function( + "getConst", + emscripten::select_overload::const_reference_type(SparseArray::size_type) const>( + &SparseArray::operator[] + ) + ) + .function( + "get", + emscripten::select_overload::reference_type(SparseArray::size_type)>( + &SparseArray::operator[] + ) + ) + .function( + "insertAt", + emscripten::select_overload< + SparseArray::reference_type(SparseArray::size_type, SparseArray::const_reference_type)>( + &SparseArray::insert_at + ) + ) + .function( + "insertAt", + emscripten::select_overload< + SparseArray::reference_type(SparseArray::size_type, SparseArray::value_type &&)>( + &SparseArray::insert_at + ) + ) + .function("clear", &SparseArray::clear) + .function("empty", &SparseArray::empty) + .function("resize", &SparseArray::resize) + .function("set", &SparseArray::set) + .function( + "setByCopy", + emscripten::select_overload &(SparseArray const &)>(&SparseArray::operator=) + ) + .function( + "setByMove", + emscripten::select_overload &(SparseArray &&)>(&SparseArray::operator=) + ); + } +} // namespace nfo diff --git a/packages/ecs/wasm/SparseArray.hpp b/packages/ecs/wasm/SparseArray.hpp new file mode 100644 index 0000000..95c57ce --- /dev/null +++ b/packages/ecs/wasm/SparseArray.hpp @@ -0,0 +1,175 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#pragma once + +#include +#include +#include +#include + +namespace nfo { + template + class SparseArray { + public: + using value_type = std::optional; + using reference_type = value_type &; + using move_reference_type = value_type &&; + using const_reference_type = value_type const &; + using container = std::vector; + using size_type = typename container::size_type; + using iterator = typename container::iterator; + using const_iterator = typename container::const_iterator; + + SparseArray() = default; + + SparseArray(SparseArray const &other) : _data(other._data) {} + + SparseArray(SparseArray &&other) noexcept : _data(std::move(other._data)) {} + + SparseArray &operator=(SparseArray const &other) + { + if (this != &other) { + _data = other._data; + } + return *this; + } + + SparseArray &operator=(SparseArray &&other) noexcept + { + if (this != &other) { + _data = std::move(other._data); + } + return *this; + } + + void erase(const size_type &idx) + { + if (idx < _data.size()) { + _data[idx].reset(); + } + } + + iterator begin() + { + return _data.begin(); + } + + [[nodiscard]] const_iterator begin() const + { + return _data.begin(); + } + + [[nodiscard]] const_iterator cbegin() const + { + return _data.cbegin(); + } + + iterator end() + { + return _data.end(); + } + + [[nodiscard]] const_iterator end() const + { + return _data.end(); + } + + [[nodiscard]] const_iterator cend() const + { + return _data.cend(); + } + + reference_type operator[](size_type idx) + { + if (idx >= _data.size()) { + _data.resize(idx + 1); + } + return _data[idx]; + } + + const_reference_type operator[](size_type idx) const + { + if (idx >= _data.size()) { + return _opt_null; + } + return _data[idx]; + } + + void set(size_type idx, value_type value) + { + (*this)[idx] = std::move(value); + } + + [[nodiscard]] size_type size() const + { + return _data.size(); + } + + void resize(size_type size) + { + _data.resize(size); + } + + void clear() + { + _data.clear(); + } + + [[nodiscard]] bool empty() const + { + return _data.empty() || std::ranges::all_of(_data, [](const auto &v) { return !v.has_value(); }); + } + + reference_type insert_at(size_type idx, const_reference_type value) + { + if (idx >= _data.size()) { + _data.resize(idx + 1); + } + _data[idx] = value; + return _data[idx]; + } + + reference_type insert_at(size_type idx, move_reference_type value) + { + if (idx >= _data.size()) { + _data.resize(idx + 1); + } + _data[idx] = std::move(value); + return _data[idx]; + } + + template + reference_type emplace_at(size_type idx, Params &&...params) + { + if (idx >= _data.size()) { + _data.resize(idx + 1); + } + _data[idx] = value_type(std::forward(params)...); + return _data[idx]; + } + + [[nodiscard]] size_type get_index(const_reference_type value) const + { + auto it = std::find(_data.begin(), _data.end(), value); + if (it != _data.end()) { + return static_cast(std::distance(_data.begin(), it)); + } + return _data.size(); + } + + private: + const value_type _opt_null = std::nullopt; + container _data; + }; +} // namespace nfo diff --git a/packages/ecs/wasm/Utils.cpp b/packages/ecs/wasm/Utils.cpp new file mode 100644 index 0000000..ad9ee3c --- /dev/null +++ b/packages/ecs/wasm/Utils.cpp @@ -0,0 +1,56 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#include "Utils.hpp" + +#include + +std::optional json_to_str(const emscripten::val &c) +{ + if (!c.isString()) + return std::nullopt; + return c.as(); +} + +std::optional get_js_member(const emscripten::val &c, const std::string &member) +{ + if (c.isUndefined() || c.isNull()) + return std::nullopt; + return c[member]; +} + +std::string get_js_class_name(const emscripten::val &c) +{ + return get_js_class_type_name(c).value_or(get_js_class_var_name(c).value_or(UNKNOWN_COMPONENT_TYPE)); +} + +std::optional get_js_class_type_name(const emscripten::val &c) +{ + const std::optional name = get_js_member(c, "name"); + if (name.has_value()) { + return json_to_str(name.value()); + } + return std::nullopt; +} + +std::optional get_js_class_var_name(const emscripten::val &c) +{ + const std::optional constructor = get_js_member(c, "constructor"); + if (constructor.has_value()) { + const std::optional name = get_js_member(constructor.value(), "name"); + if (name.has_value()) { + return json_to_str(name.value()); + } + } + return std::nullopt; +} diff --git a/packages/ecs/wasm/Utils.hpp b/packages/ecs/wasm/Utils.hpp new file mode 100644 index 0000000..1b7bd09 --- /dev/null +++ b/packages/ecs/wasm/Utils.hpp @@ -0,0 +1,29 @@ +/*⠀ ⠀⠀ ⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀ +**⠀⠀ ⠀⢀⣠⣾⡿⠿⠛⠛⠛⠛⠿⢿⣷⣄⡀⠀⠀⠀ +** _ __ ______ ⠀ ⠀ ⣰⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣆⠀⠀ +** / | / /___ _____ ____ / ____/___ _________ ____ ⠀ ⣾⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣷⠀ +** / |/ / __ `/ __ \/ __ \/ /_ / __ \/ ___/ __ `/ _ \ ⢰⣿⠃⠀⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⠤⠀⠀⠘⣿⡆ +** / /| / /_/ / / / / /_/ / __/ / /_/ / / / /_/ / __/ ⢸⣿⠀⠀⠀⠉⠛⠛⢻⣿⣿⣿⠉⠀⠀⠀⠀⠀⣿⡇ +** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ +** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ +** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ +** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +**⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ +*/ + +#pragma once + +#include +#include +#include + +#define UNKNOWN_COMPONENT_TYPE "__magic_unkown_component_type" + +EMSCRIPTEN_DECLARE_VAL_TYPE(Component); +EMSCRIPTEN_DECLARE_VAL_TYPE(ComponentArray); + +std::optional json_to_str(const emscripten::val &c); +std::optional get_js_member(const emscripten::val &c, const std::string &member); +std::string get_js_class_name(const emscripten::val &c); +std::optional get_js_class_type_name(const emscripten::val &c); +std::optional get_js_class_var_name(const emscripten::val &c); diff --git a/packages/graphics-2d/.gitignore b/packages/graphics-2d/.gitignore new file mode 100644 index 0000000..ddfd782 --- /dev/null +++ b/packages/graphics-2d/.gitignore @@ -0,0 +1,267 @@ +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Private + +# NX +.nx/ + +# Compiled files +src/**/*.js +src/**/*.d.ts diff --git a/packages/graphics-2d/.idea/.gitignore b/packages/graphics-2d/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/packages/graphics-2d/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/packages/graphics-2d/.idea/.name b/packages/graphics-2d/.idea/.name new file mode 100644 index 0000000..81d68e2 --- /dev/null +++ b/packages/graphics-2d/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine Graphics 2D \ No newline at end of file diff --git a/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml b/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/codeStyles/Project.xml b/packages/graphics-2d/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a57ead7 --- /dev/null +++ b/packages/graphics-2d/.idea/codeStyles/Project.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml b/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/editor.xml b/packages/graphics-2d/.idea/editor.xml new file mode 100644 index 0000000..8c39ae0 --- /dev/null +++ b/packages/graphics-2d/.idea/editor.xml @@ -0,0 +1,107 @@ + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/git_toolbox_blame.xml b/packages/graphics-2d/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/packages/graphics-2d/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/git_toolbox_prj.xml b/packages/graphics-2d/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/packages/graphics-2d/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml b/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..41ec19c --- /dev/null +++ b/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/jsLinters/eslint.xml b/packages/graphics-2d/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/packages/graphics-2d/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/misc.xml b/packages/graphics-2d/.idea/misc.xml new file mode 100644 index 0000000..7ecbce5 --- /dev/null +++ b/packages/graphics-2d/.idea/misc.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/modules.xml b/packages/graphics-2d/.idea/modules.xml new file mode 100644 index 0000000..59ac9e2 --- /dev/null +++ b/packages/graphics-2d/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/prettier.xml b/packages/graphics-2d/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/packages/graphics-2d/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/vcs.xml b/packages/graphics-2d/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/packages/graphics-2d/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.nvmrc b/packages/graphics-2d/.nvmrc new file mode 100644 index 0000000..c9758a5 --- /dev/null +++ b/packages/graphics-2d/.nvmrc @@ -0,0 +1 @@ +v23.6.0 diff --git a/packages/graphics-2d/.prettierignore b/packages/graphics-2d/.prettierignore new file mode 100644 index 0000000..e814a63 --- /dev/null +++ b/packages/graphics-2d/.prettierignore @@ -0,0 +1,8 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lock + +*.js +*.d.ts diff --git a/packages/graphics-2d/.prettierrc b/packages/graphics-2d/.prettierrc new file mode 100644 index 0000000..d5f635c --- /dev/null +++ b/packages/graphics-2d/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderParserPlugins": ["typescript", "decorators-legacy"], + "importOrder": ["^~/(.*)$", "^[./]"], + "useTabs": false, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/packages/graphics-2d/README.md b/packages/graphics-2d/README.md new file mode 100644 index 0000000..5d16e80 --- /dev/null +++ b/packages/graphics-2d/README.md @@ -0,0 +1 @@ +# Engine Graphics 2D diff --git a/packages/graphics-2d/eslint.config.js b/packages/graphics-2d/eslint.config.js new file mode 100644 index 0000000..4a7529e --- /dev/null +++ b/packages/graphics-2d/eslint.config.js @@ -0,0 +1,63 @@ +import pluginJs from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginJest from "eslint-plugin-jest"; + +export default [ + { + files: ["src/**/*.{ts}"], + }, + { languageOptions: { globals: globals.node } }, + + + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.strict, + eslintConfigPrettier, + { ignores: ["**/*.js"] }, + { + rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + disallowTypeAnnotations: true, + fixStyle: "inline-type-imports", + prefer: "type-imports", + }, + ], + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/member-ordering": [ + "error", + { + default: [ + "static-field", + "field", + "public-static-method", + "constructor", + "method", + "protected-method", + "private-method", + ], + }, + ], + }, + }, + { + files: ["**/*.spec.ts"], + plugins: { jest: pluginJest }, + languageOptions: { + globals: pluginJest.environments.globals.globals, + }, + rules: { + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + } + } +]; diff --git a/packages/graphics-2d/jest.config.json b/packages/graphics-2d/jest.config.json new file mode 100644 index 0000000..b75e6b6 --- /dev/null +++ b/packages/graphics-2d/jest.config.json @@ -0,0 +1,12 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": "test", + "collectCoverageFrom": ["**/*.(t|j)s"], + "testEnvironment": "node", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "verbose": true, + "testTimeout": 5000 +} diff --git a/packages/graphics-2d/package.json b/packages/graphics-2d/package.json new file mode 100644 index 0000000..d637e56 --- /dev/null +++ b/packages/graphics-2d/package.json @@ -0,0 +1,70 @@ +{ + "name": "@nanoforge/graphics-2d", + "version": "1.0.0", + "description": "NanoForge Engine - Graphics 2D", + "homepage": "https://github.com/NanoForge-dev/Engine#readme", + "license": "MIT", + "contributors": [ + "Bill", + "Exelo", + "Fexkoser", + "Tchips" + ], + "funding": { + "type": "individual", + "url": "" + }, + "type": "module", + "main": "src/index.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Engine.git", + "directory": "packages/graphics-2d" + }, + "scripts": { + "build": "tsc -b .", + "clean": "pnpm clean:types && pnpm clean:scripts && rm -f tsconfig.build.tsbuildinfo", + "clean:types": "find src -name '*.d.ts' -delete", + "clean:scripts": "find src -name '*.js' -delete", + "lint": "eslint . && prettier --check .", + "fix": "eslint . --fix && prettier --write .", + "taze": "taze major -w", + "lint-staged": "lint-staged", + "test:unit": "jest --config ./jest.config.json" + }, + "dependencies": { + "@nanoforge/asset-manager": "workspace:^", + "@nanoforge/common": "workspace:^" + }, + "devDependencies": { + "@commitlint/cli": "^19.8.0", + "@commitlint/config-conventional": "^19.8.0", + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/jest": "^29.5.14", + "@types/node": "^22.13.10", + "@webgpu/types": "^0.1.56", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "jest": "^29.7.0", + "lint-staged": "^15.4.3", + "prettier": "^3.5.3", + "ts-jest": "^29.2.6", + "typescript": "^5.8.2", + "typescript-eslint": "^8.26.0" + }, + "engines": { + "node": "23.6.0", + "pnpm": "10.6.2" + }, + "lint-staged": { + "**/*.{js,ts}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/packages/graphics-2d/src/components/component.ts b/packages/graphics-2d/src/components/component.ts new file mode 100644 index 0000000..23e4f97 --- /dev/null +++ b/packages/graphics-2d/src/components/component.ts @@ -0,0 +1,132 @@ +import type { GraphicsCore } from "../core"; +import type { ShaderManager } from "../shader/shader.manager"; + +export abstract class NfgComponent { + private readonly _core: GraphicsCore; + protected readonly _shaderManager: ShaderManager; + private _vertices: Float32Array; + protected _vertexBuffer: GPUBuffer; + protected abstract _vertexLength: number; + protected abstract readonly _vertexBufferLayout: GPUVertexBufferLayout; + private _uniformBuffer: GPUBuffer; + protected abstract _shader: GPUShaderModule; + private _pipeline: GPURenderPipeline; + private readonly _pipelineLayout: GPUPipelineLayout; + private readonly _label: string; + private _bindGroup: GPUBindGroup; + protected _duplicate: number = 1; + + constructor(core: GraphicsCore) { + this._core = core; + this._shaderManager = core.shaderManager; + this._label = `${this.constructor.name} - ${Date.now()}`; + + const bindGroupLayout = this._core.device.createBindGroupLayout({ + label: `${this._label} Bind Group Layout`, + entries: [ + { + binding: 0, + visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, + buffer: {}, + }, + ], + }); + + this._pipelineLayout = this._core.device.createPipelineLayout({ + label: `${this._label} Pipeline Layout`, + bindGroupLayouts: [bindGroupLayout], + }); + } + + public async init(): Promise { + await this._init(); + this.updateUniforms(); + this._updatePipeline(); + return this; + } + + public draw(pass: GPURenderPassEncoder): void { + pass.setPipeline(this._pipeline); + pass.setBindGroup(0, this._bindGroup); + pass.setVertexBuffer(0, this._vertexBuffer); + pass.draw(this._vertices.length / this._vertexLength, this._duplicate); + } + + public updateUniforms(): void { + const uniformArray = new Float32Array([ + 0, + 0, + 0, + 1, + 1, + 1, + this._core.initContext.canvas.width, + this._core.initContext.canvas.height, + ]); + console.log(this._core.initContext.canvas.width, this._core.initContext.canvas.height); + if (!this._uniformBuffer) + this._uniformBuffer = this._core.device.createBuffer({ + label: "View Uniforms", + size: uniformArray.byteLength, + usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + this._core.device.queue.writeBuffer(this._uniformBuffer, 0, uniformArray); + } + + protected abstract _init(): Promise; + + protected _setVertices(raw: number[]): void { + const len = this._vertices?.byteLength ?? -1; + this._vertices = new Float32Array(raw); + if (len !== this._vertices.byteLength) this._updateVertexBuffer(); + else this._writeVertexBuffer(); + } + + protected _updateVertexBuffer(): void { + this._vertexBuffer = this._core.device.createBuffer({ + label: `${this._label} vertices`, + size: this._vertices.byteLength, + usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, + }); + this._writeVertexBuffer(); + } + + protected _writeVertexBuffer(): void { + this._core.device.queue.writeBuffer(this._vertexBuffer, 0, this._vertices); + } + + protected _updatePipeline(): void { + this._pipeline = this._core.device.createRenderPipeline({ + label: `${this._label} pipeline`, + layout: this._pipelineLayout, + vertex: { + module: this._shader, + entryPoint: "vertex_main", + buffers: [this._vertexBufferLayout], + }, + fragment: { + module: this._shader, + entryPoint: "fragment_main", + targets: [ + { + format: this._core.render.canvasFormat, + }, + ], + }, + }); + this._updateBindGroup(); + } + + protected _updateBindGroup(): void { + this._bindGroup = this._core.device.createBindGroup({ + label: `${this._label} renderer bind group`, + layout: this._pipeline.getBindGroupLayout(0), + entries: [ + { + binding: 0, + resource: { buffer: this._uniformBuffer }, + }, + ], + }); + } +} diff --git a/packages/graphics-2d/src/components/index.ts b/packages/graphics-2d/src/components/index.ts new file mode 100644 index 0000000..90d87fc --- /dev/null +++ b/packages/graphics-2d/src/components/index.ts @@ -0,0 +1,2 @@ +export { NfgComponent } from "./component"; +export * from "./shape"; diff --git a/packages/graphics-2d/src/components/shape/common/shape.ts b/packages/graphics-2d/src/components/shape/common/shape.ts new file mode 100644 index 0000000..f136e97 --- /dev/null +++ b/packages/graphics-2d/src/components/shape/common/shape.ts @@ -0,0 +1,3 @@ +import { NfgComponent } from "../../component"; + +export abstract class NfgShape extends NfgComponent {} diff --git a/packages/graphics-2d/src/components/shape/index.ts b/packages/graphics-2d/src/components/shape/index.ts new file mode 100644 index 0000000..0b1d008 --- /dev/null +++ b/packages/graphics-2d/src/components/shape/index.ts @@ -0,0 +1,2 @@ +export { NfgShape } from "./common/shape"; +export * from "./shapes"; diff --git a/packages/graphics-2d/src/components/shape/shapes/circle.shape.ts b/packages/graphics-2d/src/components/shape/shapes/circle.shape.ts new file mode 100644 index 0000000..bbe369b --- /dev/null +++ b/packages/graphics-2d/src/components/shape/shapes/circle.shape.ts @@ -0,0 +1,93 @@ +import { type GraphicsCore } from "../../../core"; +import { ShadersEnum } from "../../../shader/shaders.enum"; +import { type ICircleOptions, type IColor, type IVertex2D } from "../../../types"; +import { NfgShape } from "../common/shape"; + +export class NfgCircle extends NfgShape { + protected _shader: GPUShaderModule; + protected readonly _vertexBufferLayout: GPUVertexBufferLayout; + protected _vertexLength: number; + + private _pos: IVertex2D; + private _radius: number; + private _color: IColor; + + constructor(core: GraphicsCore, options?: Partial) { + super(core); + + this._vertexBufferLayout = { + arrayStride: 28, + attributes: [ + { + format: "float32x2", + offset: 0, + shaderLocation: 0, + }, + { + format: "float32", + offset: 8, + shaderLocation: 1, + }, + { + format: "float32x4", + offset: 12, + shaderLocation: 2, + }, + ], + }; + this._vertexLength = 7; + + this._pos = options?.pos ?? { x: 0, y: 0 }; + this._radius = options?.radius ?? 0.1; + this._color = options?.color ?? { r: 0, g: 0, b: 0, a: 1 }; + this._updateVertices(); + } + + public setPosition(pos: IVertex2D): NfgCircle { + this._pos = pos; + this._updateVertices(); + return this; + } + + public setRadius(radius: number): NfgCircle { + this._radius = radius; + this._updateVertices(); + return this; + } + + public setColor(color: IColor): NfgCircle { + this._color = color; + this._updateVertices(); + return this; + } + + protected async _init(): Promise { + this._shader = await this._shaderManager.get(ShadersEnum.CIRCLE); + } + + protected _updateVertices(): void { + this._setVertices([ + this._pos.x, + this._pos.y, + this._radius, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._pos.x, + this._pos.y, + this._radius, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._pos.x, + this._pos.y, + this._radius, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + ]); + } +} diff --git a/packages/graphics-2d/src/components/shape/shapes/index.ts b/packages/graphics-2d/src/components/shape/shapes/index.ts new file mode 100644 index 0000000..e306fef --- /dev/null +++ b/packages/graphics-2d/src/components/shape/shapes/index.ts @@ -0,0 +1,2 @@ +export { NfgCircle } from "./circle.shape"; +export { NfgRectangle } from "./rectangle.shape"; diff --git a/packages/graphics-2d/src/components/shape/shapes/rectangle.shape.ts b/packages/graphics-2d/src/components/shape/shapes/rectangle.shape.ts new file mode 100644 index 0000000..0c70e3a --- /dev/null +++ b/packages/graphics-2d/src/components/shape/shapes/rectangle.shape.ts @@ -0,0 +1,122 @@ +import { type GraphicsCore } from "../../../core"; +import { ShadersEnum } from "../../../shader/shaders.enum"; +import { type IColor, type IRectangleOptions, type IVertex2D } from "../../../types"; +import { NfgShape } from "../common/shape"; + +export class NfgRectangle extends NfgShape { + protected _shader: GPUShaderModule; + protected readonly _vertexBufferLayout: GPUVertexBufferLayout; + protected _vertexLength: number; + + private _min: IVertex2D; + private _max: IVertex2D; + private _color: IColor; + + constructor(core: GraphicsCore, options?: Partial) { + super(core); + + this._vertexBufferLayout = { + arrayStride: 32, + attributes: [ + { + format: "float32x2", + offset: 0, + shaderLocation: 0, + }, + { + format: "float32x2", + offset: 8, + shaderLocation: 1, + }, + { + format: "float32x4", + offset: 16, + shaderLocation: 2, + }, + ], + }; + this._vertexLength = 8; + + this._duplicate = 1; + + this._min = options?.min ?? { x: 0, y: 0 }; + this._max = options?.max ?? { x: 0, y: 0 }; + this._color = options?.color ?? { r: 0, g: 0, b: 0, a: 1 }; + this._updateVertices(); + } + + public setMin(pos: IVertex2D): NfgRectangle { + this._min = pos; + this._updateVertices(); + return this; + } + + public setMax(pos: IVertex2D): NfgRectangle { + this._max = pos; + this._updateVertices(); + return this; + } + + public setColor(color: IColor): NfgRectangle { + this._color = color; + this._updateVertices(); + return this; + } + + protected async _init(): Promise { + this._shader = await this._shaderManager.get(ShadersEnum.RECTANGLE); + } + + protected _updateVertices(): void { + this._setVertices([ + this._min.x, + this._min.y, + this._max.x, + this._max.y, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._min.x, + this._min.y, + this._max.x, + this._max.y, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._min.x, + this._min.y, + this._max.x, + this._max.y, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._min.x, + this._min.y, + this._max.x, + this._max.y, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._min.x, + this._min.y, + this._max.x, + this._max.y, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + this._min.x, + this._min.y, + this._max.x, + this._max.y, + this._color.r, + this._color.g, + this._color.b, + this._color.a, + ]); + } +} diff --git a/packages/graphics-2d/src/core.ts b/packages/graphics-2d/src/core.ts new file mode 100644 index 0000000..e957385 --- /dev/null +++ b/packages/graphics-2d/src/core.ts @@ -0,0 +1,67 @@ +import { type InitContext } from "@nanoforge/common"; + +import { GraphicsRender } from "./render"; +import { NfgWindow } from "./render/window"; +import { ShaderManager } from "./shader/shader.manager"; + +export class GraphicsCore { + private readonly _initContext: InitContext; + + private readonly _shaderManager: ShaderManager; + private _render: GraphicsRender; + private _window: NfgWindow; + + private _adapter: GPUAdapter; + private _device: GPUDevice; + + constructor(context: InitContext) { + this._initContext = context; + + this._shaderManager = new ShaderManager(this); + } + + get initContext(): InitContext { + return this._initContext; + } + + get adapter(): GPUAdapter { + return this._adapter; + } + + get device(): GPUDevice { + return this._device; + } + + get shaderManager(): ShaderManager { + return this._shaderManager; + } + + get render(): GraphicsRender { + return this._render; + } + + get window(): NfgWindow { + return this._window; + } + + public async init(): Promise { + if (!navigator.gpu) { + throw new Error("WebGPU not supported on this browser."); + } + + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) { + throw new Error("No appropriate GPUAdapter found."); + } + this._adapter = adapter; + + const device = await this._adapter.requestDevice(); + if (!device) { + throw new Error("No appropriate GPUDevice found."); + } + this._device = device; + + this._render = new GraphicsRender(this, this._initContext); + this._window = new NfgWindow(this._render); + } +} diff --git a/packages/graphics-2d/src/factory.ts b/packages/graphics-2d/src/factory.ts new file mode 100644 index 0000000..8575c9f --- /dev/null +++ b/packages/graphics-2d/src/factory.ts @@ -0,0 +1,19 @@ +import { NfgCircle, NfgRectangle } from "./components"; +import { type GraphicsCore } from "./core"; +import { type ICircleOptions, type IRectangleOptions } from "./types"; + +export class GraphicsFactory { + private readonly _core: GraphicsCore; + + constructor(core: GraphicsCore) { + this._core = core; + } + + createCircle(options?: Partial): Promise { + return new NfgCircle(this._core, options).init(); + } + + createRectangle(options?: Partial): Promise { + return new NfgRectangle(this._core, options).init(); + } +} diff --git a/packages/graphics-2d/src/graphics-2d.library.ts b/packages/graphics-2d/src/graphics-2d.library.ts new file mode 100644 index 0000000..7be4d75 --- /dev/null +++ b/packages/graphics-2d/src/graphics-2d.library.ts @@ -0,0 +1,35 @@ +import { BaseGraphicsLibrary, type InitContext } from "@nanoforge/common"; + +import { GraphicsCore } from "./core"; +import { GraphicsFactory } from "./factory"; +import { type NfgWindow } from "./render/window"; + +export class Graphics2DLibrary extends BaseGraphicsLibrary { + private _core: GraphicsCore; + private _factory: GraphicsFactory; + + get name(): string { + return "Graphics2DLibrary"; + } + + get factory(): GraphicsFactory { + return this._factory; + } + + public async init(context: InitContext): Promise { + if (!context.canvas) { + throw new Error("Can't initialize the canvas context"); + } + this._core = new GraphicsCore(context); + await this._core.init(); + this._factory = new GraphicsFactory(this._core); + } + + public async run(): Promise { + this._core.window.render(); + } + + public getWindow(): NfgWindow { + return this._core.window; + } +} diff --git a/packages/graphics-2d/src/index.ts b/packages/graphics-2d/src/index.ts new file mode 100644 index 0000000..3199628 --- /dev/null +++ b/packages/graphics-2d/src/index.ts @@ -0,0 +1,5 @@ +import "./shader/shaders"; + +export * from "./types"; +export * from "./components"; +export { Graphics2DLibrary } from "./graphics-2d.library"; diff --git a/packages/graphics-2d/src/render.ts b/packages/graphics-2d/src/render.ts new file mode 100644 index 0000000..3c26b4f --- /dev/null +++ b/packages/graphics-2d/src/render.ts @@ -0,0 +1,73 @@ +import { type InitContext } from "@nanoforge/common"; + +import { type NfgComponent } from "./components"; +import { type GraphicsCore } from "./core"; + +export class GraphicsRender { + private readonly _core: GraphicsCore; + private readonly _canvas: HTMLCanvasElement; + private readonly _canvasContext: GPUCanvasContext; + private readonly _canvasFormat: GPUTextureFormat; + + constructor(core: GraphicsCore, initContext: InitContext) { + this._core = core; + + this._canvas = initContext.canvas; + + const context = initContext.canvas.getContext("webgpu"); + if (!context) { + throw new Error("Could not get canvas context."); + } + this._canvasContext = context; + + this._canvasFormat = navigator.gpu.getPreferredCanvasFormat(); + + this._canvasContext.configure({ + device: this._core.device, + format: this._canvasFormat, + alphaMode: "premultiplied", + }); + } + + get canvas(): HTMLCanvasElement { + return this._canvas; + } + + get canvasFormat(): GPUTextureFormat { + return this._canvasFormat; + } + + render(components: NfgComponent[]): void { + const [encoder, pass] = this._beginRender(); + this._renderComponents(pass, components); + this._endRender(pass, encoder); + } + + private _beginRender(): [GPUCommandEncoder, GPURenderPassEncoder] { + const encoder = this._core.device.createCommandEncoder(); + + const pass = encoder.beginRenderPass({ + colorAttachments: [ + { + view: this._canvasContext.getCurrentTexture().createView(), + loadOp: "clear", + clearValue: { r: 0, g: 0, b: 0.4, a: 1.0 }, + storeOp: "store", + }, + ], + }); + + return [encoder, pass]; + } + + private _renderComponents(pass: GPURenderPassEncoder, components: NfgComponent[]): void { + for (const component of components) { + component.draw(pass); + } + } + + private _endRender(pass: GPURenderPassEncoder, encoder: GPUCommandEncoder): void { + pass.end(); + this._core.device.queue.submit([encoder.finish()]); + } +} diff --git a/packages/graphics-2d/src/render/window.ts b/packages/graphics-2d/src/render/window.ts new file mode 100644 index 0000000..0ffa959 --- /dev/null +++ b/packages/graphics-2d/src/render/window.ts @@ -0,0 +1,55 @@ +import { type NfgComponent } from "../components/component"; +import { type GraphicsRender } from "../render"; + +export class NfgWindow { + private _components: NfgComponent[] = []; + private _render: GraphicsRender; + private _uniformTimeout: boolean = false; + private _uniformNeed: boolean = false; + + constructor(render: GraphicsRender) { + this._render = render; + + window.addEventListener("resize", () => { + this._updateWindowSize(); + }); + this._updateWindowSize(); + } + + get width(): number { + return this._render.canvas.width; + } + + get height(): number { + return this._render.canvas.height; + } + + public draw(component: NfgComponent) { + this._components.push(component); + } + + public render(): void { + if (this._uniformNeed) { + this.updateAllUniforms(); + this._uniformNeed = false; + } + this._render.render(this._components); + this._components = []; + } + + private _updateWindowSize(): void { + this._render.canvas.width = window.innerWidth; + this._render.canvas.height = window.innerHeight; + // Uncomment if need performances + // if (this._uniformTimeout) return; + this._uniformTimeout = true; + this._uniformNeed = true; + setTimeout(() => { + this._uniformTimeout = false; + }, 100); + } + + private updateAllUniforms(): void { + this._components.forEach((component) => component.updateUniforms()); + } +} diff --git a/packages/graphics-2d/src/shader/shader.manager.ts b/packages/graphics-2d/src/shader/shader.manager.ts new file mode 100644 index 0000000..728b76b --- /dev/null +++ b/packages/graphics-2d/src/shader/shader.manager.ts @@ -0,0 +1,49 @@ +import { type AssetManagerLibrary } from "@nanoforge/asset-manager"; + +import { type GraphicsCore } from "../core"; +import { SHADER_NAMES, SHADER_PATHS } from "./shaders.const"; +import { type ShadersEnum } from "./shaders.enum"; + +export class ShaderManager { + private _core: GraphicsCore; + private _assetManager: AssetManagerLibrary; + private _shaders: Map; + + constructor(core: GraphicsCore) { + this._core = core; + this._assetManager = + this._core.initContext.libraries.getAssetManager().library; + this._shaders = new Map(); + } + + /** + * @todo Error handling + */ + public async get(shader: ShadersEnum, reftech = true): Promise { + const res = this._shaders.get(shader); + if (!res) { + if (!reftech) throw new Error("Could not find shader"); + await this._loadShader(shader); + return this.get(shader, false); + } + return res; + } + + /** + * @todo Error handling + */ + private async _loadShader(shader: ShadersEnum): Promise { + const path = SHADER_PATHS[shader]; + if (!path) { + throw new Error("Could not find shader"); + } + const shaderFile = await this._assetManager.getWgsl(path); + this._shaders.set( + shader, + this._core.device.createShaderModule({ + label: SHADER_NAMES[shader], + code: await shaderFile.getText(), + }), + ); + } +} diff --git a/packages/graphics-2d/src/shader/shaders.const.ts b/packages/graphics-2d/src/shader/shaders.const.ts new file mode 100644 index 0000000..28a40b9 --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders.const.ts @@ -0,0 +1,11 @@ +import { ShadersEnum } from "./shaders.enum"; + +export const SHADER_PATHS: Record = { + [ShadersEnum.RECTANGLE]: "rectangle.wgsl", + [ShadersEnum.CIRCLE]: "circle.wgsl", +}; + +export const SHADER_NAMES: Record = { + [ShadersEnum.RECTANGLE]: "Rectangle shader", + [ShadersEnum.CIRCLE]: "Circle shader", +}; diff --git a/packages/graphics-2d/src/shader/shaders.enum.ts b/packages/graphics-2d/src/shader/shaders.enum.ts new file mode 100644 index 0000000..d65b22f --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders.enum.ts @@ -0,0 +1,4 @@ +export enum ShadersEnum { + RECTANGLE = 0, + CIRCLE = 1, +} diff --git a/packages/graphics-2d/src/shader/shaders/circle.wgsl b/packages/graphics-2d/src/shader/shaders/circle.wgsl new file mode 100644 index 0000000..72061be --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders/circle.wgsl @@ -0,0 +1,74 @@ +var VERTICES: array, 3> = array, 3>( + vec2(-1.7321,-1.0), + vec2( 1.7321,-1.0), + vec2( 0.0 , 2.0), +); + +struct View { + position: vec4, + scale: vec2, + size: vec2, +}; + +@group(0) +@binding(0) +var view: View; + +struct VertexInput { + @builtin(vertex_index) index: u32 +}; + +struct InstanceInput { + @location(0) position: vec2, + @location(1) radius: f32, + @location(2) color: vec4, +}; + +struct VertexOutput { + @builtin(position) clip_space: vec4, + @location(0) local_space: vec2, + @location(1) color: vec4, + @location(2) pixel_size: f32, +}; + +@vertex +fn vertex_main( + vertex: VertexInput, + instance: InstanceInput, +) -> VertexOutput { + var out: VertexOutput; + + let x = view.size.x; + let y = view.size.y; + let aspect = y / x; + + let local_space = VERTICES[vertex.index]; + + var position = instance.position; + var radius = instance.radius; + if radius * y < 1.414214 * view.scale.x { + let a = (position - view.position.xy) / view.scale.x; + let b = (floor(a * y) + 0.5) / y; + let c = b * view.scale.x + view.position.xy; + position = c; + radius = 1.414214 * view.scale.x / y; + } + + let world_space = local_space * radius + position; + + let view_space = (world_space - view.position.xy) / view.scale.x; + + let clip_space = vec4(view_space.x * aspect, view_space.y, 0.0, 1.0); + + out.clip_space = clip_space; + out.local_space = local_space; + out.color = vec4(pow(instance.color.rgb, vec3(2.2)), instance.color.a); + out.pixel_size = view.scale.x / (radius * y); + return out; +} + +@fragment +fn fragment_main(in: VertexOutput) -> @location(0) vec4 { + let alpha = 1.0 - smoothstep(1.0 - 3.0 * in.pixel_size, 1.0, length(in.local_space)); + return vec4(in.color.rgb, in.color.a * alpha); +} diff --git a/packages/graphics-2d/src/shader/shaders/index.ts b/packages/graphics-2d/src/shader/shaders/index.ts new file mode 100644 index 0000000..d361846 --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders/index.ts @@ -0,0 +1,2 @@ +import "./circle.wgsl"; +import "./rectangle.wgsl"; diff --git a/packages/graphics-2d/src/shader/shaders/rectangle.wgsl b/packages/graphics-2d/src/shader/shaders/rectangle.wgsl new file mode 100644 index 0000000..7838ee6 --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders/rectangle.wgsl @@ -0,0 +1,54 @@ +struct View { + position: vec4, + scale: vec2, + size: vec2, +}; + +@group(0) +@binding(0) +var view: View; + +struct VertexInput { + @builtin(vertex_index) index: u32 +}; + +struct InstanceInput { + @location(0) min: vec2, + @location(1) max: vec2, + @location(2) color: vec4, +}; + +struct VertexOutput { + @builtin(position) clip_space: vec4, + @location(0) color: vec4, +}; + +@vertex +fn vertex_main( + vertex: VertexInput, + instance: InstanceInput, +) -> VertexOutput { + var result: VertexOutput; + + let x = view.size.x; + let y = view.size.y; + let aspect = y / x; + + var local_space = vec2(f32(vertex.index & 1u), f32(vertex.index >> 1u)); + if vertex.index >= 3 { + local_space = vec2(f32(vertex.index & 1u), f32((vertex.index >> 1u) - 1u)); + } + let position = instance.min + local_space * (instance.max - instance.min); + + let view_space = (position - view.position.xy) / view.scale.x; + let clip_space = vec4(view_space.x * aspect, view_space.y, 0.0, 1.0); + + result.clip_space = clip_space; + result.color = instance.color; + return result; +} + +@fragment +fn fragment_main(vertex: VertexOutput) -> @location(0) vec4 { + return vertex.color; +} diff --git a/packages/graphics-2d/src/types/common/color.type.ts b/packages/graphics-2d/src/types/common/color.type.ts new file mode 100644 index 0000000..a5bc4c5 --- /dev/null +++ b/packages/graphics-2d/src/types/common/color.type.ts @@ -0,0 +1,6 @@ +export interface IColor { + r: number; + g: number; + b: number; + a: number; +} diff --git a/packages/graphics-2d/src/types/common/index.ts b/packages/graphics-2d/src/types/common/index.ts new file mode 100644 index 0000000..84737ae --- /dev/null +++ b/packages/graphics-2d/src/types/common/index.ts @@ -0,0 +1,4 @@ +export { IColor } from "./color.type"; +export { ISize } from "./size.type"; +export { IVertex2D } from "./vertex-2d.type"; +export { IVertex4D } from "./vertex-4d.type"; diff --git a/packages/graphics-2d/src/types/common/size.type.ts b/packages/graphics-2d/src/types/common/size.type.ts new file mode 100644 index 0000000..8264d49 --- /dev/null +++ b/packages/graphics-2d/src/types/common/size.type.ts @@ -0,0 +1,4 @@ +export interface ISize { + height: number; + width: number; +} diff --git a/packages/graphics-2d/src/types/common/vertex-2d.type.ts b/packages/graphics-2d/src/types/common/vertex-2d.type.ts new file mode 100644 index 0000000..4f4cc74 --- /dev/null +++ b/packages/graphics-2d/src/types/common/vertex-2d.type.ts @@ -0,0 +1,4 @@ +export interface IVertex2D { + x: number; + y: number; +} diff --git a/packages/graphics-2d/src/types/common/vertex-4d.type.ts b/packages/graphics-2d/src/types/common/vertex-4d.type.ts new file mode 100644 index 0000000..c24bf2d --- /dev/null +++ b/packages/graphics-2d/src/types/common/vertex-4d.type.ts @@ -0,0 +1,6 @@ +export interface IVertex4D { + x: number; + y: number; + z: number; + w: number; +} diff --git a/packages/graphics-2d/src/types/index.ts b/packages/graphics-2d/src/types/index.ts new file mode 100644 index 0000000..3f4c0d3 --- /dev/null +++ b/packages/graphics-2d/src/types/index.ts @@ -0,0 +1,2 @@ +export * from "./common"; +export * from "./options"; diff --git a/packages/graphics-2d/src/types/options/base/color.type.ts b/packages/graphics-2d/src/types/options/base/color.type.ts new file mode 100644 index 0000000..33a3773 --- /dev/null +++ b/packages/graphics-2d/src/types/options/base/color.type.ts @@ -0,0 +1,5 @@ +import { type IColor } from "../../common"; + +export interface IColorOption { + color: IColor; +} diff --git a/packages/graphics-2d/src/types/options/base/position.type.ts b/packages/graphics-2d/src/types/options/base/position.type.ts new file mode 100644 index 0000000..b46070f --- /dev/null +++ b/packages/graphics-2d/src/types/options/base/position.type.ts @@ -0,0 +1,5 @@ +import { type IVertex2D } from "../../common"; + +export interface IPositionOption { + pos: IVertex2D; +} diff --git a/packages/graphics-2d/src/types/options/base/size.type.ts b/packages/graphics-2d/src/types/options/base/size.type.ts new file mode 100644 index 0000000..a455eb8 --- /dev/null +++ b/packages/graphics-2d/src/types/options/base/size.type.ts @@ -0,0 +1,5 @@ +import { type ISize } from "../../common"; + +export interface ISizeOption { + size: ISize; +} diff --git a/packages/graphics-2d/src/types/options/final/circle-options.type.ts b/packages/graphics-2d/src/types/options/final/circle-options.type.ts new file mode 100644 index 0000000..c0af50c --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/circle-options.type.ts @@ -0,0 +1,6 @@ +import { type IColorOption } from "../base/color.type"; +import { type IPositionOption } from "../base/position.type"; + +export interface ICircleOptions extends IColorOption, IPositionOption { + radius: number; +} diff --git a/packages/graphics-2d/src/types/options/final/index.ts b/packages/graphics-2d/src/types/options/final/index.ts new file mode 100644 index 0000000..d9c15e8 --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/index.ts @@ -0,0 +1,3 @@ +export { ICircleOptions } from "./circle-options.type"; +export { IRectangleOptions } from "./rectangle-options.type"; +export { IRoundedRectangleOptions } from "./rounded-rectangle-options.type"; diff --git a/packages/graphics-2d/src/types/options/final/rectangle-options.type.ts b/packages/graphics-2d/src/types/options/final/rectangle-options.type.ts new file mode 100644 index 0000000..1040464 --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/rectangle-options.type.ts @@ -0,0 +1,7 @@ +import { type IVertex2D } from "../../common"; +import { type IColorOption } from "../base/color.type"; + +export interface IRectangleOptions extends IColorOption { + min: IVertex2D; + max: IVertex2D; +} diff --git a/packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts b/packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts new file mode 100644 index 0000000..8ab9981 --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts @@ -0,0 +1,5 @@ +import { type IRectangleOptions } from "./rectangle-options.type"; + +export interface IRoundedRectangleOptions extends IRectangleOptions { + round: number; +} diff --git a/packages/graphics-2d/src/types/options/index.ts b/packages/graphics-2d/src/types/options/index.ts new file mode 100644 index 0000000..c320d6b --- /dev/null +++ b/packages/graphics-2d/src/types/options/index.ts @@ -0,0 +1 @@ +export * from "./final"; diff --git a/packages/graphics-2d/src/utils/string.ts b/packages/graphics-2d/src/utils/string.ts new file mode 100644 index 0000000..9d539ad --- /dev/null +++ b/packages/graphics-2d/src/utils/string.ts @@ -0,0 +1,7 @@ +export const formatUpperToLisible = (value: string) => { + return capitalize(value.toLowerCase().replace("_", " ")); +}; + +export const capitalize = (value: string) => { + return value.charAt(0).toUpperCase() + value.slice(1); +}; diff --git a/packages/graphics-2d/test/graphics-2d.library.spec.ts b/packages/graphics-2d/test/graphics-2d.library.spec.ts new file mode 100644 index 0000000..67b5f09 --- /dev/null +++ b/packages/graphics-2d/test/graphics-2d.library.spec.ts @@ -0,0 +1,22 @@ +import { ApplicationContext, InitContext, LibraryManager } from "@nanoforge/common"; + +import { Graphics2DLibrary } from "../src/graphics-2d.library"; + +describe("Graphics 2D Library", () => { + const library = new Graphics2DLibrary(); + const appContext = new ApplicationContext(); + const libraryManager = new LibraryManager(); + const context = new InitContext(appContext, libraryManager, { + // @ts-ignore + canvas: null, + files: { + assets: new Map([["/test.png", "blob:http://localhost:3000/test.png"]]), + wasm: new Map([["/test.wasm", "blob:http://localhost:3000/test.wasm"]]), + wgsl: new Map([["/test.wgsl", "blob:http://localhost:3000/test.wgsl"]]), + }, + }); + + it("Should throw if canvas is undefined", async () => { + await expect(library.init(context)).rejects.toThrow(); + }); +}); diff --git a/packages/graphics-2d/test/tsconfig.json b/packages/graphics-2d/test/tsconfig.json new file mode 100644 index 0000000..e756f49 --- /dev/null +++ b/packages/graphics-2d/test/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../../tsconfig.spec.json", + "compilerOptions": { + "types": ["jest", "node", "@webgpu/types"] + } +} diff --git a/packages/graphics-2d/tsconfig.build.json b/packages/graphics-2d/tsconfig.build.json new file mode 100644 index 0000000..610404e --- /dev/null +++ b/packages/graphics-2d/tsconfig.build.json @@ -0,0 +1,21 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "types": ["node", "@webgpu/types"], + "outDir": ".", + "rootDir": ".", + "paths": { + "@nanoforge/common": ["../common"], + "@nanoforge/asset-manager": ["../asset-manager"] + } + }, + "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], + "references": [ + { + "path": "../common/tsconfig.build.json" + }, + { + "path": "../asset-manager/tsconfig.build.json" + } + ] +} diff --git a/packages/graphics-2d/tsconfig.json b/packages/graphics-2d/tsconfig.json new file mode 100644 index 0000000..875a64e --- /dev/null +++ b/packages/graphics-2d/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "types": ["jest", "node", "@webgpu/types"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.build.json" + } + ] +} diff --git a/packages/input/.gitignore b/packages/input/.gitignore new file mode 100644 index 0000000..9f6061c --- /dev/null +++ b/packages/input/.gitignore @@ -0,0 +1,272 @@ +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Private + +# NX +.nx/ + +# Compiled files +src/**/*.js +src/**/*.d.ts + +# pubilc directory +public/ +compile_commands.json +emsdk/ diff --git a/packages/input/.idea/.gitignore b/packages/input/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/packages/input/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/packages/input/.idea/.name b/packages/input/.idea/.name new file mode 100644 index 0000000..c81648b --- /dev/null +++ b/packages/input/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine Input \ No newline at end of file diff --git a/packages/input/.idea/[NanoForge] Engine Input.iml b/packages/input/.idea/[NanoForge] Engine Input.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/packages/input/.idea/[NanoForge] Engine Input.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/input/.idea/codeStyles/Project.xml b/packages/input/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a57ead7 --- /dev/null +++ b/packages/input/.idea/codeStyles/Project.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/input/.idea/codeStyles/codeStyleConfig.xml b/packages/input/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/packages/input/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/input/.idea/editor.xml b/packages/input/.idea/editor.xml new file mode 100644 index 0000000..d9ec4df --- /dev/null +++ b/packages/input/.idea/editor.xml @@ -0,0 +1,106 @@ + + + + + \ No newline at end of file diff --git a/packages/input/.idea/git_toolbox_blame.xml b/packages/input/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/packages/input/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/input/.idea/git_toolbox_prj.xml b/packages/input/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/packages/input/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/input/.idea/inspectionProfiles/Project_Default.xml b/packages/input/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..41ec19c --- /dev/null +++ b/packages/input/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/packages/input/.idea/jsLinters/eslint.xml b/packages/input/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000..541945b --- /dev/null +++ b/packages/input/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/input/.idea/misc.xml b/packages/input/.idea/misc.xml new file mode 100644 index 0000000..7ecbce5 --- /dev/null +++ b/packages/input/.idea/misc.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/input/.idea/modules.xml b/packages/input/.idea/modules.xml new file mode 100644 index 0000000..d1ef219 --- /dev/null +++ b/packages/input/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/input/.idea/prettier.xml b/packages/input/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/packages/input/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/packages/input/.idea/vcs.xml b/packages/input/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/packages/input/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/input/.nvmrc b/packages/input/.nvmrc new file mode 100644 index 0000000..c9758a5 --- /dev/null +++ b/packages/input/.nvmrc @@ -0,0 +1 @@ +v23.6.0 diff --git a/packages/input/.prettierignore b/packages/input/.prettierignore new file mode 100644 index 0000000..e814a63 --- /dev/null +++ b/packages/input/.prettierignore @@ -0,0 +1,8 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lock + +*.js +*.d.ts diff --git a/packages/input/.prettierrc b/packages/input/.prettierrc new file mode 100644 index 0000000..d5f635c --- /dev/null +++ b/packages/input/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderParserPlugins": ["typescript", "decorators-legacy"], + "importOrder": ["^~/(.*)$", "^[./]"], + "useTabs": false, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/packages/input/README.md b/packages/input/README.md new file mode 100644 index 0000000..33e4d47 --- /dev/null +++ b/packages/input/README.md @@ -0,0 +1 @@ +# Engine Input diff --git a/packages/input/eslint.config.js b/packages/input/eslint.config.js new file mode 100644 index 0000000..4a7529e --- /dev/null +++ b/packages/input/eslint.config.js @@ -0,0 +1,63 @@ +import pluginJs from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginJest from "eslint-plugin-jest"; + +export default [ + { + files: ["src/**/*.{ts}"], + }, + { languageOptions: { globals: globals.node } }, + + + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.strict, + eslintConfigPrettier, + { ignores: ["**/*.js"] }, + { + rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + disallowTypeAnnotations: true, + fixStyle: "inline-type-imports", + prefer: "type-imports", + }, + ], + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/member-ordering": [ + "error", + { + default: [ + "static-field", + "field", + "public-static-method", + "constructor", + "method", + "protected-method", + "private-method", + ], + }, + ], + }, + }, + { + files: ["**/*.spec.ts"], + plugins: { jest: pluginJest }, + languageOptions: { + globals: pluginJest.environments.globals.globals, + }, + rules: { + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + } + } +]; diff --git a/packages/input/package.json b/packages/input/package.json new file mode 100644 index 0000000..087a986 --- /dev/null +++ b/packages/input/package.json @@ -0,0 +1,64 @@ +{ + "name": "@nanoforge/input", + "version": "1.0.0", + "description": "NanoForge Engine - Input", + "homepage": "https://github.com/NanoForge-dev/Engine#readme", + "license": "MIT", + "contributors": [ + "Bill", + "Exelo", + "Fexkoser", + "Tchips" + ], + "funding": { + "type": "individual", + "url": "" + }, + "type": "module", + "main": "src/index.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Engine.git", + "directory": "packages/input" + }, + "scripts": { + "build": "tsc -b .", + "clean": "pnpm clean:types && pnpm clean:scripts && rm -f tsconfig.build.tsbuildinfo", + "clean:types": "find src -name '*.d.ts' -delete", + "clean:scripts": "find src -name '*.js' -delete", + "lint": "eslint . && prettier --check .", + "fix": "eslint . --fix && prettier --write .", + "taze": "taze major -w", + "lint-staged": "lint-staged" + }, + "dependencies": { + "@nanoforge/common": "workspace:^" + }, + "devDependencies": { + "@commitlint/cli": "^19.8.0", + "@commitlint/config-conventional": "^19.8.0", + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/node": "^22.13.10", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "lint-staged": "^15.4.3", + "prettier": "^3.5.3", + "typescript": "^5.8.2", + "typescript-eslint": "^8.26.0" + }, + "engines": { + "node": "23.6.0", + "pnpm": "10.6.2" + }, + "lint-staged": { + "**/*.{js,ts}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/packages/input/src/index.ts b/packages/input/src/index.ts new file mode 100644 index 0000000..7d7f3d5 --- /dev/null +++ b/packages/input/src/index.ts @@ -0,0 +1,2 @@ +export { InputLibrary } from "./input.library"; +export { InputEnum } from "./input.enum"; diff --git a/packages/input/src/input-handler.ts b/packages/input/src/input-handler.ts new file mode 100644 index 0000000..56416b0 --- /dev/null +++ b/packages/input/src/input-handler.ts @@ -0,0 +1,19 @@ +import { type InputEnum } from "./input.enum"; + +export class InputHandler { + public inputs: Record = {}; + + constructor() { + window.addEventListener("keydown", (e: KeyboardEvent) => { + this.inputs[e.code] = true; + }); + + window.addEventListener("keyup", (e: KeyboardEvent) => { + this.inputs[e.code] = false; + }); + } + + getKeyStatus(key: InputEnum): boolean { + return this.inputs[key]; + } +} diff --git a/packages/input/src/input.enum.ts b/packages/input/src/input.enum.ts new file mode 100644 index 0000000..cb1899c --- /dev/null +++ b/packages/input/src/input.enum.ts @@ -0,0 +1,144 @@ +export enum InputEnum { + Escape = "Escape", + Digit1 = "Digit1", + Digit2 = "Digit2", + Digit3 = "Digit3", + Digit4 = "Digit4", + Digit5 = "Digit5", + Digit6 = "Digit6", + Digit7 = "Digit7", + Digit8 = "Digit8", + Digit9 = "Digit9", + Digit0 = "Digit0", + Minus = "Minus", + Equal = "Equal", + Backspace = "Backspace", + Tab = "Tab", + KeyQ = "KeyQ", + KeyW = "KeyW", + KeyE = "KeyE", + KeyR = "KeyR", + KeyT = "KeyT", + KeyY = "KeyY", + KeyU = "KeyU", + KeyI = "KeyI", + KeyO = "KeyO", + KeyP = "KeyP", + BracketLeft = "BracketLeft", + BracketRight = "BracketRight", + Enter = "Enter", + ControlLeft = "ControlLeft", + KeyA = "KeyA", + KeyS = "KeyS", + KeyD = "KeyD", + KeyF = "KeyF", + KeyG = "KeyG", + KeyH = "KeyH", + KeyJ = "KeyJ", + KeyK = "KeyK", + KeyL = "KeyL", + Semicolon = "Semicolon", + Quote = "Quote", + Backquote = "Backquote", + ShiftLeft = "ShiftLeft", + Backslash = "Backslash", + KeyZ = "KeyZ", + KeyX = "KeyX", + KeyC = "KeyC", + KeyV = "KeyV", + KeyB = "KeyB", + KeyN = "KeyN", + KeyM = "KeyM", + Comma = "Comma", + Period = "Period", + Slash = "Slash", + ShiftRight = "ShiftRight", + NumpadMultiply = "NumpadMultiply", + AltLeft = "AltLeft", + Space = "Space", + CapsLock = "CapsLock", + F1 = "F1", + F2 = "F2", + F3 = "F3", + F4 = "F4", + F5 = "F5", + F6 = "F6", + F7 = "F7", + F8 = "F8", + F9 = "F9", + F10 = "F10", + Pause = "Pause", + ScrollLock = "ScrollLock", + Numpad7 = "Numpad7", + Numpad8 = "Numpad8", + Numpad9 = "Numpad9", + NumpadSubtract = "NumpadSubtract", + Numpad4 = "Numpad4", + Numpad5 = "Numpad5", + Numpad6 = "Numpad6", + NumpadAdd = "NumpadAdd", + Numpad1 = "Numpad1", + Numpad2 = "Numpad2", + Numpad3 = "Numpad3", + Numpad0 = "Numpad0", + NumpadDecimal = "NumpadDecimal", + IntlBackslash = "IntlBackslash", + F11 = "F11", + F12 = "F12", + NumpadEqual = "NumpadEqual", + F13 = "F13", + F14 = "F14", + F15 = "F15", + F16 = "F16", + F17 = "F17", + F18 = "F18", + F19 = "F19", + F20 = "F20", + F21 = "F21", + F22 = "F22", + F23 = "F23", + KanaMode = "KanaMode", + Lang2 = "Lang2", + Lang1 = "Lang1", + IntlRo = "IntlRo", + F24 = "F24", + Convert = "Convert", + NonConvert = "NonConvert", + IntlYen = "IntlYen", + NumpadComma = "NumpadComma", + MediaTrackPrevious = "MediaTrackPrevious", + MediaTrackNext = "MediaTrackNext", + NumpadEnter = "NumpadEnter", + ControlRight = "ControlRight", + AudioVolumeMute = "AudioVolumeMute", + LaunchApp2 = "LaunchApp2", + MediaPlayPause = "MediaPlayPause", + MediaStop = "MediaStop", + BrowserHome = "BrowserHome", + NumpadDivide = "NumpadDivide", + PrintScreen = "PrintScreen", + AltRight = "AltRight", + NumLock = "NumLock", + Home = "Home", + ArrowUp = "ArrowUp", + PageUp = "PageUp", + ArrowLeft = "ArrowLeft", + ArrowRight = "ArrowRight", + End = "End", + ArrowDown = "ArrowDown", + PageDown = "PageDown", + Insert = "Insert", + Delete = "Delete", + MetaLeft = "MetaLeft", + MetaRight = "MetaRight", + ContextMenu = "ContextMenu", + Power = "Power", + BrowserSearch = "BrowserSearch", + BrowserFavorites = "BrowserFavorites", + BrowserRefresh = "BrowserRefresh", + BrowserStop = "BrowserStop", + BrowserForward = "BrowserForward", + BrowserBack = "BrowserBack", + LaunchApp1 = "LaunchApp1", + LaunchMail = "LaunchMail", +} diff --git a/packages/input/src/input.library.ts b/packages/input/src/input.library.ts new file mode 100644 index 0000000..a06e373 --- /dev/null +++ b/packages/input/src/input.library.ts @@ -0,0 +1,29 @@ +import { BaseInputLibrary } from "@nanoforge/common"; + +import { InputHandler } from "./input-handler"; +import { type InputEnum } from "./input.enum"; + +export class InputLibrary extends BaseInputLibrary { + private _inputHandler: InputHandler; + + get name(): string { + return "InputLibrary"; + } + + public async init(): Promise { + this._inputHandler = new InputHandler(); + } + + public isKeyPressed(key: InputEnum): boolean { + return this._inputHandler.getKeyStatus(key); + } + + public getPressedKeys(): InputEnum[] { + const res: InputEnum[] = []; + for (const rawKey in this._inputHandler.inputs) { + const key = rawKey as InputEnum; + if (this._inputHandler.getKeyStatus(key)) res.push(key); + } + return res; + } +} diff --git a/packages/input/tsconfig.build.json b/packages/input/tsconfig.build.json new file mode 100644 index 0000000..a7e09c7 --- /dev/null +++ b/packages/input/tsconfig.build.json @@ -0,0 +1,16 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "outDir": ".", + "rootDir": ".", + "paths": { + "@nanoforge/common": ["../common"] + } + }, + "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], + "references": [ + { + "path": "../common/tsconfig.build.json" + } + ] +} diff --git a/packages/input/tsconfig.json b/packages/input/tsconfig.json new file mode 100644 index 0000000..a74c8e2 --- /dev/null +++ b/packages/input/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "types": ["jest", "node"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.build.json" + } + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 134c004..8624570 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,67 @@ importers: specifier: ^8.26.0 version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + packages/asset-manager: + dependencies: + '@nanoforge/common': + specifier: workspace:^ + version: link:../common + devDependencies: + '@commitlint/cli': + specifier: ^19.8.0 + version: 19.8.0(@types/node@22.13.10)(typescript@5.8.2) + '@commitlint/config-conventional': + specifier: ^19.8.0 + version: 19.8.0 + '@eslint/js': + specifier: ^9.22.0 + version: 9.22.0 + '@trivago/prettier-plugin-sort-imports': + specifier: ^5.2.2 + version: 5.2.2(prettier@3.5.3) + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/node': + specifier: ^22.13.10 + version: 22.13.10 + eslint: + specifier: ^9.22.0 + version: 9.22.0(jiti@2.4.2) + eslint-config-prettier: + specifier: ^10.1.1 + version: 10.1.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-format: + specifier: ^1.0.1 + version: 1.0.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-jest: + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + eslint-plugin-prettier: + specifier: ^5.2.3 + version: 5.2.3(eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))(prettier@3.5.3) + globals: + specifier: ^16.0.0 + version: 16.0.0 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.13.10) + lint-staged: + specifier: ^15.4.3 + version: 15.4.3 + prettier: + specifier: ^3.5.3 + version: 3.5.3 + ts-jest: + specifier: ^29.2.6 + version: 29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + typescript: + specifier: ^5.8.2 + version: 5.8.2 + typescript-eslint: + specifier: ^8.26.0 + version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + packages/common: devDependencies: '@commitlint/cli': @@ -157,6 +218,137 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: ^5.2.2 version: 5.2.2(prettier@3.5.3) + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/node': + specifier: ^22.13.10 + version: 22.13.10 + eslint: + specifier: ^9.22.0 + version: 9.22.0(jiti@2.4.2) + eslint-config-prettier: + specifier: ^10.1.1 + version: 10.1.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-format: + specifier: ^1.0.1 + version: 1.0.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-jest: + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + eslint-plugin-prettier: + specifier: ^5.2.3 + version: 5.2.3(eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))(prettier@3.5.3) + globals: + specifier: ^16.0.0 + version: 16.0.0 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.13.10) + lint-staged: + specifier: ^15.4.3 + version: 15.4.3 + prettier: + specifier: ^3.5.3 + version: 3.5.3 + ts-jest: + specifier: ^29.2.6 + version: 29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + typescript: + specifier: ^5.8.2 + version: 5.8.2 + typescript-eslint: + specifier: ^8.26.0 + version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + + packages/graphics-2d: + dependencies: + '@nanoforge/asset-manager': + specifier: workspace:^ + version: link:../asset-manager + '@nanoforge/common': + specifier: workspace:^ + version: link:../common + devDependencies: + '@commitlint/cli': + specifier: ^19.8.0 + version: 19.8.0(@types/node@22.13.10)(typescript@5.8.2) + '@commitlint/config-conventional': + specifier: ^19.8.0 + version: 19.8.0 + '@eslint/js': + specifier: ^9.22.0 + version: 9.22.0 + '@trivago/prettier-plugin-sort-imports': + specifier: ^5.2.2 + version: 5.2.2(prettier@3.5.3) + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/node': + specifier: ^22.13.10 + version: 22.13.10 + '@webgpu/types': + specifier: ^0.1.56 + version: 0.1.56 + eslint: + specifier: ^9.22.0 + version: 9.22.0(jiti@2.4.2) + eslint-config-prettier: + specifier: ^10.1.1 + version: 10.1.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-format: + specifier: ^1.0.1 + version: 1.0.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-jest: + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + eslint-plugin-prettier: + specifier: ^5.2.3 + version: 5.2.3(eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))(prettier@3.5.3) + globals: + specifier: ^16.0.0 + version: 16.0.0 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.13.10) + lint-staged: + specifier: ^15.4.3 + version: 15.4.3 + prettier: + specifier: ^3.5.3 + version: 3.5.3 + ts-jest: + specifier: ^29.2.6 + version: 29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + typescript: + specifier: ^5.8.2 + version: 5.8.2 + typescript-eslint: + specifier: ^8.26.0 + version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + + packages/input: + dependencies: + '@nanoforge/common': + specifier: workspace:^ + version: link:../common + devDependencies: + '@commitlint/cli': + specifier: ^19.8.0 + version: 19.8.0(@types/node@22.13.10)(typescript@5.8.2) + '@commitlint/config-conventional': + specifier: ^19.8.0 + version: 19.8.0 + '@eslint/js': + specifier: ^9.22.0 + version: 9.22.0 + '@trivago/prettier-plugin-sort-imports': + specifier: ^5.2.2 + version: 5.2.2(prettier@3.5.3) + '@types/node': + specifier: ^22.13.10 + version: 22.13.10 eslint: specifier: ^9.22.0 version: 9.22.0(jiti@2.4.2) @@ -166,6 +358,9 @@ importers: eslint-plugin-format: specifier: ^1.0.1 version: 1.0.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-jest: + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) eslint-plugin-prettier: specifier: ^5.2.3 version: 5.2.3(eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))(prettier@3.5.3) @@ -178,20 +373,57 @@ importers: prettier: specifier: ^3.5.3 version: 3.5.3 + typescript: + specifier: ^5.8.2 + version: 5.8.2 typescript-eslint: specifier: ^8.26.0 version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.10': + resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.26.9': resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} @@ -200,23 +432,138 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.10': + resolution: {integrity: sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.10': + resolution: {integrity: sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/parser@7.26.9': resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/template@7.26.9': resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.26.10': + resolution: {integrity: sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.26.9': resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} engines: {node: '>=6.9.0'} + '@babel/types@7.26.10': + resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.26.9': resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@commitlint/cli@19.8.0': resolution: {integrity: sha512-t/fCrLVu+Ru01h0DtlgHZXbHV2Y8gKocTR5elDOqIRUzQd0/6hpt2VIWOj9b3NDo7y4/gfxeR2zRtXq/qO6iUg==} engines: {node: '>=v18'} @@ -373,10 +720,80 @@ packages: '@isaacs/string-locale-compare@1.1.0': resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==} + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -627,6 +1044,12 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@trivago/prettier-plugin-sort-imports@5.2.2': resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==} engines: {node: '>18.12'} @@ -654,12 +1077,39 @@ packages: '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/conventional-commits-parser@5.0.1': resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -675,6 +1125,15 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@typescript-eslint/eslint-plugin@8.26.1': resolution: {integrity: sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -722,6 +1181,9 @@ packages: resolution: {integrity: sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@webgpu/types@0.1.56': + resolution: {integrity: sha512-JkT4ngqwk4gKAFoWtXCcC1+TGhSStVtauS9z27slOGSFYr+QqjS0CoawiAxP7Gq9xkT4Pw9uouvWPT44HwbUiw==} + '@yarnpkg/lockfile@1.1.0': resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} @@ -800,6 +1262,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} @@ -837,6 +1303,31 @@ packages: axios@1.8.2: resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -863,6 +1354,18 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -893,6 +1396,13 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001704: + resolution: {integrity: sha512-+L2IgBbV6gXB4ETf0keSvLr7JUrRVbIaB/lrQ1+z8mRcQiisG5k+lG6O4n6Y5q6f5EuNfaYXKgymucphlEXQew==} + chalk@4.1.0: resolution: {integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==} engines: {node: '>=10'} @@ -905,6 +1415,10 @@ packages: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} @@ -920,6 +1434,9 @@ packages: resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} engines: {node: '>=8'} + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -967,6 +1484,13 @@ packages: resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1049,6 +1573,9 @@ packages: engines: {node: '>=14'} hasBin: true + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -1069,6 +1596,11 @@ packages: typescript: optional: true + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1117,6 +1649,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -1135,6 +1671,10 @@ packages: resolution: {integrity: sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==} engines: {node: '>=4'} + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1170,6 +1710,13 @@ packages: engines: {node: '>=0.10.0'} hasBin: true + electron-to-chromium@1.5.116: + resolution: {integrity: sha512-mufxTCJzLBQVvSdZzX1s5YAuXsN1M4tTyYxOOL1TcSKtIzQ9rjIrm7yFK80rN5dwGTePgdoABDSHpuVtRQh0Zw==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -1232,6 +1779,10 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1255,6 +1806,19 @@ packages: peerDependencies: eslint: ^8.40.0 || ^9.0.0 + eslint-plugin-jest@28.11.0: + resolution: {integrity: sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==} + engines: {node: ^16.10.0 || ^18.12.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + eslint-plugin-prettier@5.2.3: resolution: {integrity: sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -1330,6 +1894,14 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + exponential-backoff@3.1.2: resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} @@ -1359,6 +1931,9 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -1439,9 +2014,18 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -1454,6 +2038,10 @@ packages: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + get-pkg-repo@4.2.1: resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} engines: {node: '>=6.9.0'} @@ -1515,6 +2103,10 @@ packages: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + glob@9.3.5: resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} engines: {node: '>=16 || 14 >=14.17'} @@ -1588,6 +2180,9 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -1651,6 +2246,10 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1709,6 +2308,10 @@ packages: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1777,6 +2380,30 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1788,14 +2415,135 @@ packages: javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + jiti@2.4.2: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true @@ -1875,11 +2623,19 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + lerna@8.2.1: resolution: {integrity: sha512-Xwjv9/4ixp7fpBWhtvp7dz4NoQT8DEf7hzibHKCgu/8kmZUHeXsTn+TKspHqhI+p4YDmdkDnkg8xmymz73kVOg==} engines: {node: '>=18.0.0'} hasBin: true + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1948,6 +2704,9 @@ packages: lodash.kebabcase@4.1.1: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -1980,6 +2739,9 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -1992,10 +2754,16 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + make-fetch-happen@13.0.1: resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} engines: {node: ^16.14.0 || >=18.0.0} + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -2167,9 +2935,15 @@ packages: engines: {node: ^16.14.0 || >=18.0.0} hasBin: true + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + node-machine-id@1.1.12: resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + nopt@7.2.1: resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -2186,6 +2960,10 @@ packages: resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} engines: {node: ^16.14.0 || >=18.0.0} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + npm-bundled@3.0.1: resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -2383,6 +3161,10 @@ packages: resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2434,6 +3216,10 @@ packages: resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} engines: {node: '>=10'} + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -2488,6 +3274,10 @@ packages: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + promzard@1.0.2: resolution: {integrity: sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -2502,6 +3292,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2627,6 +3420,10 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.7.1: resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} engines: {node: '>=10'} @@ -2658,6 +3455,9 @@ packages: resolution: {integrity: sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==} engines: {node: ^16.14.0 || >=18.0.0} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -2686,6 +3486,9 @@ packages: resolution: {integrity: sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==} engines: {node: '>=4'} + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -2722,10 +3525,18 @@ packages: resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2785,6 +3596,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -2805,6 +3620,10 @@ packages: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} engines: {node: '>=4'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + text-extensions@1.9.0: resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} engines: {node: '>=0.10'} @@ -2830,6 +3649,9 @@ packages: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2851,6 +3673,30 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-jest@29.2.6: + resolution: {integrity: sha512-yTNZVZqc8lSixm+QGVFcPe6+yj7+TWZwIesuOWvfcn4B9bz5x4NDzVCQQjOs7Hfouu36aEqfEbo9Qpo+gq8dDg==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + tsconfig-paths@4.2.0: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} @@ -2866,6 +3712,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + type-fest@0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} engines: {node: '>=10'} @@ -2932,6 +3782,12 @@ packages: resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} engines: {node: '>=4'} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2942,6 +3798,10 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -2952,6 +3812,9 @@ packages: walk-up-path@3.0.1: resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -3003,6 +3866,10 @@ packages: write-file-atomic@2.4.3: resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + write-file-atomic@5.0.1: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3023,6 +3890,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -3057,12 +3927,47 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.10': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helpers': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.10': + dependencies: + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + '@babel/generator@7.26.9': dependencies: '@babel/parser': 7.26.9 @@ -3071,20 +3976,154 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.26.5': {} + '@babel/helper-string-parser@7.25.9': {} '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.10': + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + + '@babel/parser@7.26.10': + dependencies: + '@babel/types': 7.26.10 + '@babel/parser@7.26.9': dependencies: '@babel/types': 7.26.9 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template@7.26.9': dependencies: '@babel/code-frame': 7.26.2 '@babel/parser': 7.26.9 '@babel/types': 7.26.9 + '@babel/traverse@7.26.10': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/traverse@7.26.9': dependencies: '@babel/code-frame': 7.26.2 @@ -3097,11 +4136,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/types@7.26.10': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/types@7.26.9': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@bcoe/v8-coverage@0.2.3': {} + '@commitlint/cli@19.8.0(@types/node@22.13.10)(typescript@5.8.2)': dependencies: '@commitlint/format': 19.8.0 @@ -3301,10 +4347,178 @@ snapshots: '@isaacs/string-locale-compare@1.1.0': {} + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.13.10) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.13.10 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 22.13.10 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.8 + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.26.10 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.10 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -3698,6 +4912,14 @@ snapshots: '@sinclair/typebox@0.27.8': {} + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.5.3)': dependencies: '@babel/generator': 7.26.9 @@ -3721,12 +4943,52 @@ snapshots: dependencies: tslib: 2.8.1 + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.9 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.9 + '@types/conventional-commits-parser@5.0.1': dependencies: '@types/node': 22.13.10 '@types/estree@1.0.6': {} + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.13.10 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/json-schema@7.0.15': {} '@types/minimatch@3.0.5': {} @@ -3739,6 +5001,14 @@ snapshots: '@types/normalize-package-data@2.4.4': {} + '@types/stack-utils@2.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -3816,6 +5086,8 @@ snapshots: '@typescript-eslint/types': 8.26.1 eslint-visitor-keys: 4.2.0 + '@webgpu/types@0.1.56': {} + '@yarnpkg/lockfile@1.1.0': {} '@yarnpkg/parsers@3.0.2': @@ -3885,6 +5157,11 @@ snapshots: ansi-styles@6.2.1: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + aproba@2.0.0: {} argparse@1.0.10: @@ -3915,6 +5192,61 @@ snapshots: transitivePeerDependencies: - debug + babel-jest@29.7.0(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.26.10) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.26.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.10) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.10) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.10) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.10) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.10) + + babel-preset-jest@29.6.3(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + balanced-match@1.0.2: {} base64-js@1.5.1: {} @@ -3947,6 +5279,21 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001704 + electron-to-chromium: 1.5.116 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + buffer-from@1.1.2: {} buffer@5.7.1: @@ -3986,6 +5333,10 @@ snapshots: camelcase@5.3.1: {} + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001704: {} + chalk@4.1.0: dependencies: ansi-styles: 4.3.0 @@ -3998,6 +5349,8 @@ snapshots: chalk@5.4.1: {} + char-regex@1.0.2: {} + chardet@0.7.0: {} chownr@2.0.0: {} @@ -4006,6 +5359,8 @@ snapshots: ci-info@4.2.0: {} + cjs-module-lexer@1.4.3: {} + clean-stack@2.2.0: {} cli-cursor@3.1.0: @@ -4049,6 +5404,10 @@ snapshots: cmd-shim@6.0.3: {} + co@4.6.0: {} + + collect-v8-coverage@1.0.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -4151,6 +5510,8 @@ snapshots: git-semver-tags: 5.0.1 meow: 8.1.2 + convert-source-map@2.0.0: {} + core-util-is@1.0.3: {} cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.10)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2): @@ -4169,6 +5530,21 @@ snapshots: optionalDependencies: typescript: 5.8.2 + create-jest@29.7.0(@types/node@22.13.10): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.13.10) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4198,6 +5574,8 @@ snapshots: deep-is@0.1.4: {} + deepmerge@4.3.1: {} + defaults@1.0.4: dependencies: clone: 1.0.4 @@ -4210,6 +5588,8 @@ snapshots: detect-indent@5.0.0: {} + detect-newline@3.1.0: {} + diff-sequences@29.6.3: {} dir-glob@3.0.1: @@ -4240,6 +5620,10 @@ snapshots: dependencies: jake: 10.9.2 + electron-to-chromium@1.5.116: {} + + emittery@0.13.1: {} + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -4290,6 +5674,8 @@ snapshots: escape-string-regexp@1.0.5: {} + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)): @@ -4314,6 +5700,17 @@ snapshots: prettier: 3.5.3 synckit: 0.9.2 + eslint-plugin-jest@28.11.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2): + dependencies: + '@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + eslint: 9.22.0(jiti@2.4.2) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + jest: 29.7.0(@types/node@22.13.10) + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-prettier@5.2.3(eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))(prettier@3.5.3): dependencies: eslint: 9.22.0(jiti@2.4.2) @@ -4422,6 +5819,16 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + exit@0.1.2: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + exponential-backoff@3.1.2: {} external-editor@3.1.0: @@ -4452,6 +5859,10 @@ snapshots: dependencies: reusify: 1.1.0 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -4533,8 +5944,13 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.3: + optional: true + function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} get-east-asian-width@1.3.0: {} @@ -4552,6 +5968,8 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-package-type@0.1.0: {} + get-pkg-repo@4.2.1: dependencies: '@hutson/parse-repository-url': 3.0.2 @@ -4622,6 +6040,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + glob@9.3.5: dependencies: fs.realpath: 1.0.0 @@ -4689,6 +6116,8 @@ snapshots: dependencies: lru-cache: 10.4.3 + html-escaper@2.0.2: {} + http-cache-semantics@4.1.1: {} http-proxy-agent@7.0.2: @@ -4744,6 +6173,11 @@ snapshots: indent-string@4.0.0: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} ini@1.3.8: {} @@ -4809,6 +6243,8 @@ snapshots: dependencies: get-east-asian-width: 1.3.0 + is-generator-fn@2.1.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -4857,6 +6293,47 @@ snapshots: isobject@3.0.1: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.26.10 + '@babel/parser': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.26.10 + '@babel/parser': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -4866,12 +6343,93 @@ snapshots: jake@10.9.2: dependencies: async: 3.2.6 - chalk: 4.1.0 + chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 javascript-natural-sort@0.7.1: {} + jest-changed-files@29.7.0: + dependencies: + execa: 5.0.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@22.13.10): + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@22.13.10) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@22.13.10) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@22.13.10): + dependencies: + '@babel/core': 7.26.10 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.10) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.13.10 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-diff@29.7.0: dependencies: chalk: 4.1.0 @@ -4879,8 +6437,226 @@ snapshots: jest-get-type: 29.6.3 pretty-format: 29.7.0 + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jest-get-type@29.6.3: {} + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.10 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.10 + resolve.exports: 2.0.3 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.26.10 + '@babel/generator': 7.26.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) + '@babel/types': 7.26.9 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@29.7.0: + dependencies: + '@types/node': 22.13.10 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@22.13.10): + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@22.13.10) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jiti@2.4.2: {} js-tokens@4.0.0: {} @@ -4938,6 +6714,8 @@ snapshots: kind-of@6.0.3: {} + kleur@3.0.3: {} + lerna@8.2.1(encoding@0.1.13): dependencies: '@lerna/create': 8.2.1(encoding@0.1.13)(typescript@5.8.2) @@ -5029,6 +6807,8 @@ snapshots: - encoding - supports-color + leven@3.1.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -5123,6 +6903,8 @@ snapshots: lodash.kebabcase@4.1.1: {} + lodash.memoize@4.1.2: {} + lodash.merge@4.6.2: {} lodash.mergewith@4.6.2: {} @@ -5152,6 +6934,10 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lru-cache@6.0.0: dependencies: yallist: 4.0.0 @@ -5165,6 +6951,8 @@ snapshots: dependencies: semver: 7.7.1 + make-error@1.3.6: {} + make-fetch-happen@13.0.1: dependencies: '@npmcli/agent': 2.2.2 @@ -5182,6 +6970,10 @@ snapshots: transitivePeerDependencies: - supports-color + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + map-obj@1.0.1: {} map-obj@4.3.0: {} @@ -5343,8 +7135,12 @@ snapshots: transitivePeerDependencies: - supports-color + node-int64@0.4.0: {} + node-machine-id@1.1.12: {} + node-releases@2.0.19: {} + nopt@7.2.1: dependencies: abbrev: 2.0.0 @@ -5369,6 +7165,8 @@ snapshots: semver: 7.7.1 validate-npm-package-license: 3.0.4 + normalize-path@3.0.0: {} + npm-bundled@3.0.1: dependencies: npm-normalize-package-bin: 3.0.1 @@ -5646,6 +7444,8 @@ snapshots: path-exists@5.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -5677,6 +7477,8 @@ snapshots: pify@5.0.0: {} + pirates@4.0.6: {} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -5717,6 +7519,11 @@ snapshots: err-code: 2.0.3 retry: 0.12.0 + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + promzard@1.0.2: dependencies: read: 3.0.1 @@ -5727,6 +7534,8 @@ snapshots: punycode@2.3.1: {} + pure-rand@6.1.0: {} + queue-microtask@1.2.3: {} quick-lru@4.0.1: {} @@ -5847,6 +7656,8 @@ snapshots: semver@5.7.2: {} + semver@6.3.1: {} + semver@7.7.1: {} set-blocking@2.0.0: {} @@ -5876,6 +7687,8 @@ snapshots: transitivePeerDependencies: - supports-color + sisteransi@1.0.5: {} + slash@3.0.0: {} slice-ansi@5.0.0: @@ -5907,6 +7720,11 @@ snapshots: dependencies: is-plain-obj: 1.1.0 + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map@0.6.1: {} spdx-correct@3.2.0: @@ -5941,8 +7759,17 @@ snapshots: dependencies: minipass: 7.1.2 + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + string-argv@0.3.2: {} + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -6001,6 +7828,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} synckit@0.9.2: @@ -6027,6 +7858,12 @@ snapshots: temp-dir@1.0.0: {} + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + text-extensions@1.9.0: {} text-extensions@2.4.0: {} @@ -6046,6 +7883,8 @@ snapshots: tmp@0.2.3: {} + tmpl@1.0.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -6060,6 +7899,25 @@ snapshots: dependencies: typescript: 5.8.2 + ts-jest@29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2): + dependencies: + bs-logger: 0.2.6 + ejs: 3.1.10 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@22.13.10) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.1 + typescript: 5.8.2 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.26.10 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.10) + tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 @@ -6080,6 +7938,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-detect@4.0.8: {} + type-fest@0.18.1: {} type-fest@0.21.3: {} @@ -6125,6 +7985,12 @@ snapshots: upath@2.0.1: {} + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -6133,6 +7999,12 @@ snapshots: uuid@10.0.0: {} + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -6142,6 +8014,10 @@ snapshots: walk-up-path@3.0.1: {} + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -6201,6 +8077,11 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 @@ -6225,6 +8106,8 @@ snapshots: y18n@5.0.8: {} + yallist@3.1.1: {} + yallist@4.0.0: {} yaml@2.7.0: {} diff --git a/tsconfig.json b/tsconfig.json index 778280d..d3f77c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,11 +18,10 @@ "baseUrl": ".", "paths": { "@nanoforge/common": ["./packages/common"], - "@nanoforge/common/*": ["./packages/common/*"], "@nanoforge/core": ["./packages/core"], - "@nanoforge/core/*": ["./packages/core/*"], + "@nanoforge/asset-manager": ["./packages/asset-manager"], "@nanoforge/ecs": ["./packages/ecs"], - "@nanoforge/ecs/*": ["./packages/ecs/*"], + "@nanoforge/graphics-2d": ["./packages/graphics-2d"] } }, "include": ["packages/**/*", "integration/**/*"], diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000..0f13797 --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["integration/**/*", "integration/**/*.spec.ts", "packages/**/*.spec.ts"], + "exclude": ["node_modules", "dist"] +}