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"]
+}