From 149877d01c4f4893066e5389b6817d855dd50430 Mon Sep 17 00:00:00 2001 From: Exelo Date: Fri, 28 Aug 2026 12:02:48 +0200 Subject: [PATCH 01/12] chore: upgrade deps (#411) --- .github/actions/pnpm-install/action.yml | 48 - .github/actions/prepare/action.yml | 18 +- .nvmrc | 2 +- docs.json | 0 e2e/game/package.json | 2 +- package.json | 4 +- packages/asset-manager/.nvmrc | 2 +- packages/asset-manager/package.json | 4 +- packages/common/.nvmrc | 2 +- packages/common/package.json | 4 +- packages/config/.nvmrc | 2 +- packages/config/package.json | 4 +- packages/core-editor/.nvmrc | 2 +- packages/core-editor/package.json | 4 +- packages/core/.nvmrc | 2 +- packages/core/package.json | 4 +- packages/ecs-client/.nvmrc | 2 +- packages/ecs-client/package.json | 4 +- packages/ecs-lib/.nvmrc | 2 +- packages/ecs-lib/package.json | 4 +- packages/ecs-server/.nvmrc | 2 +- packages/ecs-server/package.json | 4 +- packages/graphics-2d-editor/.nvmrc | 2 +- packages/graphics-2d-editor/package.json | 4 +- packages/graphics-2d/.nvmrc | 2 +- packages/graphics-2d/package.json | 4 +- packages/input/.nvmrc | 2 +- packages/input/package.json | 4 +- packages/music/.nvmrc | 2 +- packages/music/package.json | 4 +- packages/network-client/.nvmrc | 2 +- packages/network-client/package.json | 4 +- packages/network-server/.nvmrc | 2 +- packages/network-server/package.json | 4 +- packages/sound/.nvmrc | 2 +- packages/sound/package.json | 4 +- pnpm-lock.yaml | 3153 ++++++++++++---------- pnpm-workspace.yaml | 24 +- utils/eslint-config/package.json | 4 +- utils/prettier-config/package.json | 4 +- 40 files changed, 1819 insertions(+), 1530 deletions(-) delete mode 100644 .github/actions/pnpm-install/action.yml delete mode 100644 docs.json diff --git a/.github/actions/pnpm-install/action.yml b/.github/actions/pnpm-install/action.yml deleted file mode 100644 index 6a6dff16..00000000 --- a/.github/actions/pnpm-install/action.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: "pnpm install" -description: "Run pnpm install with cache enabled" -inputs: - path: - description: "Path to the directory containing the pnpm workspace" - default: "." -runs: - using: "composite" - steps: - - name: Set up swap space - if: runner.os == 'Linux' - uses: pierotofy/set-swap-space@v1.0 - with: - swap-size-gb: 10 - - - uses: pnpm/action-setup@v4.1.0 - name: Install pnpm - with: - run_install: false - package_json_file: ${{ inputs.path }}/package.json - - - name: Expose pnpm config(s) through "$GITHUB_OUTPUT" - id: pnpm-config - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Cache rotation keys - id: cache-rotation - shell: bash - run: | - echo "YEAR_MONTH=$(/bin/date -u "+%Y%m")" >> $GITHUB_OUTPUT - - - uses: actions/cache@v4 - name: Setup pnpm cache - with: - path: ${{ steps.pnpm-config.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-cache-${{ steps.cache-rotation.outputs.YEAR_MONTH }}-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store-cache-${{ steps.cache-rotation.outputs.YEAR_MONTH }}- - - - name: Install dependencies - shell: bash - run: | - pnpm install --frozen-lockfile --prefer-offline --loglevel error - env: - HUSKY: "0" - working-directory: ${{ inputs.path }} diff --git a/.github/actions/prepare/action.yml b/.github/actions/prepare/action.yml index 5a33c279..1f6fedc3 100644 --- a/.github/actions/prepare/action.yml +++ b/.github/actions/prepare/action.yml @@ -1,9 +1,6 @@ name: prepare description: Prepare action inputs: - node-install: - description: Install node - default: "true" pnpm-install: description: Install pnpm depedencies default: "true" @@ -16,17 +13,12 @@ inputs: runs: using: composite steps: - - if: inputs.node-install == 'true' - name: Install Node.js - uses: actions/setup-node@v6 - with: - node-version: 25 - package-manager-cache: false - registry-url: https://registry.npmjs.org - - if: inputs.pnpm-install == 'true' - name: Install dependencies - uses: ./.github/actions/pnpm-install + name: Install pnpm and Node.js + uses: pnpm/setup@c9883cc79df532ad1a7b81bf9ab944ceb090d65c + with: + runtime: node@26 + cache: true - if: inputs.emsdk-install == 'true' name: Install emsdk diff --git a/.nvmrc b/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/docs.json b/docs.json deleted file mode 100644 index e69de29b..00000000 diff --git a/e2e/game/package.json b/e2e/game/package.json index ec977fd5..8c5a4e56 100644 --- a/e2e/game/package.json +++ b/e2e/game/package.json @@ -25,6 +25,6 @@ }, "private": true, "engines": { - "node": "25" + "node": "26" } } diff --git a/package.json b/package.json index acbbd933..a893b2c5 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,9 @@ "typescript": "catalog:core", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.9.0", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "private": true, "lint-staged": { diff --git a/packages/asset-manager/.nvmrc b/packages/asset-manager/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/asset-manager/.nvmrc +++ b/packages/asset-manager/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/asset-manager/package.json b/packages/asset-manager/package.json index 21fade03..c3b9e33f 100644 --- a/packages/asset-manager/package.json +++ b/packages/asset-manager/package.json @@ -71,9 +71,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/common/.nvmrc b/packages/common/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/common/.nvmrc +++ b/packages/common/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/common/package.json b/packages/common/package.json index 0d0ef331..daf766aa 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -68,9 +68,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/config/.nvmrc b/packages/config/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/config/.nvmrc +++ b/packages/config/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/config/package.json b/packages/config/package.json index f81b0c34..283e98b0 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -70,9 +70,9 @@ "typescript": "catalog:core", "unrun": "catalog:build" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/core-editor/.nvmrc b/packages/core-editor/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/core-editor/.nvmrc +++ b/packages/core-editor/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/core-editor/package.json b/packages/core-editor/package.json index 2e9267aa..b227b2f3 100644 --- a/packages/core-editor/package.json +++ b/packages/core-editor/package.json @@ -76,9 +76,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/core/.nvmrc b/packages/core/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/core/.nvmrc +++ b/packages/core/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/core/package.json b/packages/core/package.json index 94a308f8..efd95ea4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -75,9 +75,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/ecs-client/.nvmrc b/packages/ecs-client/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/ecs-client/.nvmrc +++ b/packages/ecs-client/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/ecs-client/package.json b/packages/ecs-client/package.json index a7618a11..a4896c9c 100644 --- a/packages/ecs-client/package.json +++ b/packages/ecs-client/package.json @@ -80,9 +80,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/ecs-lib/.nvmrc b/packages/ecs-lib/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/ecs-lib/.nvmrc +++ b/packages/ecs-lib/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/ecs-lib/package.json b/packages/ecs-lib/package.json index d52e82eb..d058a130 100644 --- a/packages/ecs-lib/package.json +++ b/packages/ecs-lib/package.json @@ -75,9 +75,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/ecs-server/.nvmrc b/packages/ecs-server/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/ecs-server/.nvmrc +++ b/packages/ecs-server/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/ecs-server/package.json b/packages/ecs-server/package.json index 43f64ba5..d6c2f8bd 100644 --- a/packages/ecs-server/package.json +++ b/packages/ecs-server/package.json @@ -80,9 +80,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/graphics-2d-editor/.nvmrc b/packages/graphics-2d-editor/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/graphics-2d-editor/.nvmrc +++ b/packages/graphics-2d-editor/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/graphics-2d-editor/package.json b/packages/graphics-2d-editor/package.json index 1e2e84bb..79b29a2b 100644 --- a/packages/graphics-2d-editor/package.json +++ b/packages/graphics-2d-editor/package.json @@ -73,9 +73,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/graphics-2d/.nvmrc b/packages/graphics-2d/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/graphics-2d/.nvmrc +++ b/packages/graphics-2d/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/graphics-2d/package.json b/packages/graphics-2d/package.json index 54ba5e5f..2e0af3e6 100644 --- a/packages/graphics-2d/package.json +++ b/packages/graphics-2d/package.json @@ -72,9 +72,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/input/.nvmrc b/packages/input/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/input/.nvmrc +++ b/packages/input/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/input/package.json b/packages/input/package.json index 591f296c..536dd170 100644 --- a/packages/input/package.json +++ b/packages/input/package.json @@ -71,9 +71,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/music/.nvmrc b/packages/music/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/music/.nvmrc +++ b/packages/music/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/music/package.json b/packages/music/package.json index f667f9a6..f5dfed97 100644 --- a/packages/music/package.json +++ b/packages/music/package.json @@ -71,9 +71,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/network-client/.nvmrc b/packages/network-client/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/network-client/.nvmrc +++ b/packages/network-client/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/network-client/package.json b/packages/network-client/package.json index 3bbda112..f9ecf2c7 100644 --- a/packages/network-client/package.json +++ b/packages/network-client/package.json @@ -72,9 +72,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/network-server/.nvmrc b/packages/network-server/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/network-server/.nvmrc +++ b/packages/network-server/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/network-server/package.json b/packages/network-server/package.json index 512f91b1..92357362 100644 --- a/packages/network-server/package.json +++ b/packages/network-server/package.json @@ -76,9 +76,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/packages/sound/.nvmrc b/packages/sound/.nvmrc index a682cfb9..4aa0e0a7 100644 --- a/packages/sound/.nvmrc +++ b/packages/sound/.nvmrc @@ -1 +1 @@ -v25 +v26 diff --git a/packages/sound/package.json b/packages/sound/package.json index e72f2c6d..e64a4193 100644 --- a/packages/sound/package.json +++ b/packages/sound/package.json @@ -71,9 +71,9 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f6ba3b69..1608cfc4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,18 +7,18 @@ settings: catalogs: build: tsdown: - specifier: ^0.22.3 - version: 0.22.3 + specifier: ^0.22.14 + version: 0.22.14 unrun: specifier: ^0.3.0 version: 0.3.1 ci: '@commitlint/cli': - specifier: ^21.2.0 - version: 21.2.0 + specifier: ^21.2.2 + version: 21.2.2 '@commitlint/config-conventional': - specifier: ^21.2.0 - version: 21.2.0 + specifier: ^21.2.2 + version: 21.2.2 '@favware/cliff-jumper': specifier: ^6.0.0 version: 6.1.0 @@ -29,8 +29,8 @@ catalogs: specifier: ^9.1.7 version: 9.1.7 lint-staged: - specifier: ^17.0.8 - version: 17.0.8 + specifier: ^17.3.0 + version: 17.3.0 config: class-transformer: specifier: ^0.5.1 @@ -40,18 +40,18 @@ catalogs: version: 0.14.4 core: '@types/node': - specifier: ^26.0.1 - version: 26.0.1 + specifier: ^26.4.0 + version: 26.4.0 turbo: - specifier: ^2.10.1 - version: 2.10.1 + specifier: ^2.10.12 + version: 2.10.12 typescript: - specifier: ^6.0.3 - version: 6.0.3 + specifier: ^7.0.2 + version: 7.0.2 docs: '@microsoft/api-extractor': - specifier: ^7.58.9 - version: 7.58.9 + specifier: ^7.59.0 + version: 7.59.0 mint-tsdocs: specifier: ^0.0.8 version: 0.0.8 @@ -67,8 +67,8 @@ catalogs: specifier: ^6.0.2 version: 6.0.2 eslint: - specifier: ^10.6.0 - version: 10.6.0 + specifier: ^10.9.1 + version: 10.9.1 eslint-config-prettier: specifier: ^10.1.8 version: 10.1.8 @@ -85,8 +85,8 @@ catalogs: specifier: ^17.3.0 version: 17.7.0 prettier: - specifier: ^3.9.4 - version: 3.9.1 + specifier: ^3.9.6 + version: 3.9.6 typescript-eslint: specifier: ^8.61.0 version: 8.62.0 @@ -105,11 +105,11 @@ catalogs: version: 8.21.0 test: '@vitest/coverage-v8': - specifier: ^4.1.9 - version: 4.1.9 + specifier: ^4.1.11 + version: 4.1.11 vitest: - specifier: ^4.1.9 - version: 4.1.9 + specifier: ^4.1.11 + version: 4.1.11 importers: @@ -117,13 +117,13 @@ importers: devDependencies: '@commitlint/cli': specifier: catalog:ci - version: 21.2.0(@types/node@26.0.1)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3) + version: 21.2.2(@types/node@26.4.0)(conventional-commits-parser@7.1.2)(typescript@7.0.2) '@commitlint/config-conventional': specifier: catalog:ci - version: 21.2.0 + version: 21.2.2 '@microsoft/api-extractor': specifier: catalog:docs - version: 7.58.9(@types/node@26.0.1) + version: 7.59.0(@types/node@26.4.0) '@nanoforge-dev/actions': specifier: catalog:ci version: 2.1.5 @@ -135,40 +135,40 @@ importers: version: link:utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.4) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) '@types/node': specifier: catalog:core - version: 26.0.1 + version: 26.4.0 '@vitest/coverage-v8': specifier: catalog:test - version: 4.1.9(vitest@4.1.9) + version: 4.1.11(vitest@4.1.11) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) husky: specifier: catalog:ci version: 9.1.7 lint-staged: specifier: catalog:ci - version: 17.0.8 + version: 17.3.0 mint-tsdocs: specifier: catalog:docs - version: 0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.0.1)(@typescript-eslint/parser@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3))(eslint@10.6.0(jiti@2.6.1))(react-dom@18.3.1(react@18.3.1))(typescript@6.0.3) + version: 0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.4.0)(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(react-dom@18.3.1(react@18.3.1))(supports-color@10.2.2)(typescript@7.0.2) prettier: specifier: catalog:lint - version: 3.9.4 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) turbo: specifier: catalog:core - version: 2.10.1 + version: 2.10.12 typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) e2e/game: devDependencies: @@ -177,7 +177,7 @@ importers: version: link:../../packages/asset-manager '@nanoforge-dev/cli': specifier: latest - version: 1.6.0(@types/node@26.0.1) + version: 1.6.2(@types/node@26.4.0) '@nanoforge-dev/common': specifier: workspace:* version: link:../../packages/common @@ -210,7 +210,7 @@ importers: version: link:../../packages/sound typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 example/pong-network: devDependencies: @@ -219,7 +219,7 @@ importers: version: link:../../packages/asset-manager '@nanoforge-dev/cli': specifier: latest - version: 1.6.0(@types/node@26.0.1) + version: 1.6.2(@types/node@26.4.0) '@nanoforge-dev/common': specifier: workspace:* version: link:../../packages/common @@ -261,19 +261,19 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) lint-staged: specifier: catalog:ci - version: 17.0.8 + version: 17.3.0 prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 packages/asset-manager: dependencies: @@ -292,25 +292,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/common: devDependencies: @@ -325,25 +325,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/config: dependencies: @@ -365,19 +365,19 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) @@ -411,25 +411,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/core-editor: dependencies: @@ -463,25 +463,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/ecs-client: dependencies: @@ -509,28 +509,28 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) '@types/node': specifier: catalog:core - version: 26.0.1 + version: 26.4.0 eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/ecs-lib: dependencies: @@ -549,28 +549,28 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) '@types/node': specifier: catalog:core - version: 26.0.1 + version: 26.4.0 eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/ecs-server: dependencies: @@ -598,28 +598,28 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) '@types/node': specifier: catalog:core - version: 26.0.1 + version: 26.4.0 eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/graphics-2d: dependencies: @@ -641,25 +641,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/graphics-2d-editor: dependencies: @@ -684,25 +684,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/input: dependencies: @@ -721,25 +721,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/music: dependencies: @@ -758,25 +758,25 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/network-client: dependencies: @@ -798,31 +798,31 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/network-server: dependencies: '@mapbox/node-pre-gyp': specifier: catalog:network - version: 2.0.3 + version: 2.0.3(supports-color@10.2.2) '@nanoforge-dev/common': specifier: workspace:* version: link:../common @@ -847,28 +847,28 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) '@types/ws': specifier: catalog:network version: 8.18.1 eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) packages/sound: dependencies: @@ -887,65 +887,65 @@ importers: version: link:../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 6.0.3 + version: 7.0.2 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) utils/eslint-config: dependencies: '@eslint/js': specifier: catalog:lint - version: 10.0.1(eslint@10.6.0(jiti@2.6.1)) + version: 10.0.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) '@favware/cliff-jumper': specifier: catalog:ci version: 6.1.0 eslint-config-prettier: specifier: catalog:lint - version: 10.1.8(eslint@10.6.0(jiti@2.6.1)) + version: 10.1.8(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) eslint-formatter-pretty: specifier: catalog:lint version: 7.1.0 eslint-plugin-format: specifier: catalog:lint - version: 2.0.1(eslint@10.6.0(jiti@2.6.1)) + version: 2.0.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) eslint-plugin-prettier: specifier: catalog:lint - version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.6.0(jiti@2.6.1)))(eslint@10.6.0(jiti@2.6.1))(prettier@3.9.1) + version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(prettier@3.9.6) globals: specifier: catalog:lint version: 17.7.0 typescript-eslint: specifier: catalog:lint - version: 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) + version: 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) devDependencies: '@nanoforge-dev/utils-prettier-config': specifier: workspace:* version: link:../prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint - version: 10.6.0(jiti@2.6.1) + version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 utils/prettier-config: devDependencies: @@ -954,10 +954,10 @@ importers: version: 6.1.0 '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier@3.9.1) + version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) prettier: specifier: catalog:lint - version: 3.9.1 + version: 3.9.6 packages: @@ -979,36 +979,32 @@ packages: '@actions/io@3.0.2': resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - '@angular-devkit/core@21.2.17': - resolution: {integrity: sha512-JbGWwFX1Nv4Np0S9b4HP2SUKhR2bz6l/S8zBXnam95+RXzDaqXJDmQHOHZGS+4La06SjlcXwFyrgSI0rm50A1A==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/core@22.1.6': + resolution: {integrity: sha512-KLBsZoc2RhOy0xSdeYcLoSOqV/fBP3feBmhY9o12ry2IuyW/17sCmWr6XbIfTIYQN6M98Y1ewmwVNFsvV5b0gA==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^5.0.0 peerDependenciesMeta: chokidar: optional: true - '@angular-devkit/schematics-cli@21.2.17': - resolution: {integrity: sha512-aMsH04Cr+pUhmPRO1bf552o/UFBlOpk+zPKHUY1BwR0dZCgMmZAf/AK5M1TrquAV5Vp9YfNwV/tJ2HOU3dSOHw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/schematics-cli@22.1.6': + resolution: {integrity: sha512-KO+vQiWgWW6i2H3XGu1E6AeZ6cyeehF1WTejATEZ3f02LROBkGyZGDAmdtSPtd3tmaGt3TVY25Mq1laybByKMA==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular-devkit/schematics@21.2.17': - resolution: {integrity: sha512-IMsbo/OBG0mdCRxezbq/CLo6JxUJBOAHZfbUDzxbSRwJm8FT5AbXO7rW+Z3haoqcb+WrC5Pr+DQ6WolX2x2brQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/schematics@22.1.6': + resolution: {integrity: sha512-IbDO9KbQyQm20uinsfT8d9ZtQw41/WVutI/65mAw39WZfN8Ky+MOgOUJCGLiSccMprvZ9YdodBTnN9bLH149Ag==} + engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.7': - resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} engines: {node: '>=6.9.0'} - '@babel/generator@8.0.0': - resolution: {integrity: sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==} - engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helper-globals@7.29.7': resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} @@ -1017,44 +1013,27 @@ packages: resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@8.0.0': - resolution: {integrity: sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==} - engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@8.0.2': - resolution: {integrity: sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==} - engines: {node: ^22.18.0 || >=24.11.0} - - '@babel/parser@7.29.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@8.0.0': - resolution: {integrity: sha512-aLxAE+imI9bCcyaPrUDjBv3uSkWieifjLe0kuFOZF0zli0L6GCsTmsePnTr55adbIAgYz2zhN1vnFimCBUYcRQ==} - engines: {node: ^22.18.0 || >=24.11.0} - hasBin: true - '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} - '@babel/types@8.0.0': - resolution: {integrity: sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==} - engines: {node: ^22.18.0 || >=24.11.0} - '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -1069,13 +1048,13 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@commitlint/cli@21.2.0': - resolution: {integrity: sha512-4GLVIhUaT3c3GBlQ0GB80/5H3xXdn/Tgw4lrsuoOQVDu2wl4Xw0GuzSar8xZKSMv4H3xaKaQXmvH91GmdyYBZA==} + '@commitlint/cli@21.2.2': + resolution: {integrity: sha512-a+6hQxIxnpdvSvS2apvttPNbEliYsVC3PqFYDiiB2kjbwIsQsj1urvQ4Tkf70pKYozPalKAuRQmm/GHwndduqA==} engines: {node: '>=22.12.0'} hasBin: true - '@commitlint/config-conventional@21.2.0': - resolution: {integrity: sha512-Qf8WRDVcyVd14if6VTWenebxFbKnVnbzPUJjlzjkyJGeHK2xCGd63Dr1XZzj0plXKQb9P0BfOxoc1HVeCo2BWQ==} + '@commitlint/config-conventional@21.2.2': + resolution: {integrity: sha512-NxA37SZviusFUEYOQZ5hNnZ1h7O/KiemPkxjOlpzKJNnWxThiwc6/SaZhaPa8fyLvfRBAywhQhJJk8XESHWlpQ==} engines: {node: '>=22.12.0'} '@commitlint/config-validator@21.2.0': @@ -1090,40 +1069,40 @@ packages: resolution: {integrity: sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==} engines: {node: '>=22.12.0'} - '@commitlint/format@21.2.0': - resolution: {integrity: sha512-c4q64xaav2U83t7k7RyzJerBZurPer7FxUOY0RL5L/6CZijZ7K+s6HIBGIghj0ey1P2+seRX0J9XQYtDued6tg==} + '@commitlint/format@21.2.2': + resolution: {integrity: sha512-v6fvxZSc/AvVMROlr3H34+1766bZSYApRUSCAMjWamStPjKMvZ8GdvVA5YW/VQNgbFTmcMz6OYmSTJEvIjPrfA==} engines: {node: '>=22.12.0'} - '@commitlint/is-ignored@21.2.0': - resolution: {integrity: sha512-4/eB0vBN7L88O/oC4ajAEqi7j2ZfNgxl/+11RfAV9YosejZgDXhY2C9VcHnHJhOzPLoSy5P3Mg/46kqeyJfXKw==} + '@commitlint/is-ignored@21.2.2': + resolution: {integrity: sha512-9UoKNgfFE3LU7FrzierCvk3CdDfMDeVGC86qZiT/n0TIjfq/dmZ9MHuXd45OTNRa26ZanmJRxEtmiXk/lEJihg==} engines: {node: '>=22.12.0'} - '@commitlint/lint@21.2.0': - resolution: {integrity: sha512-ceO5dp9pLjEZ6y6qbq/uXWXDPykqqlTsyzoQ0NzecpisSJhK3kTy9qzQoPeJuWG/IMNdV1lO0RgmzqoAlSi1uw==} + '@commitlint/lint@21.2.2': + resolution: {integrity: sha512-Fy8JxEBzdmsYWFude/61GxXu5O+wEymwiRK2z9GL9R8mCsXphCoGxAFc5iHn5mjlfcSrhiiONE+ksf4KOjnaPg==} engines: {node: '>=22.12.0'} - '@commitlint/load@21.2.0': - resolution: {integrity: sha512-RjlzWQqruRwIenJEfZtq7kG97co97nKoHpflE5YnF61tDLXxHPrdWImgzw6VL6MlFyaOcVlk74eBV8ZQmc3oIA==} + '@commitlint/load@21.2.2': + resolution: {integrity: sha512-0Tt6wDPX167cjKC5D4zhm0+20wJJG+TN/TKovMOspfSe78rOnKX+MNzlVNiu6HyQPZChPJ8QBH31MVt6Bb8fCg==} engines: {node: '>=22.12.0'} '@commitlint/message@21.2.0': resolution: {integrity: sha512-YxGoiXD/HXNXLJPrQwE5poXa+XH0CBEm+mdvbHQP0g6MV/dmJyUFCzPNzZbxL93GvZ70TmtTK0Z0/IBpAqHv8g==} engines: {node: '>=22.12.0'} - '@commitlint/parse@21.2.0': - resolution: {integrity: sha512-QHWxG4d0PLTF634/AdyZ0MQS+CLn5YOuJlCFhMMlSGKFxzYGUetkHBj18xgBD+6fVzUrA2lrCdi/vlS2f/oYXg==} + '@commitlint/parse@21.2.2': + resolution: {integrity: sha512-MEkobPfvRp+z06Wro8HMG1BDGHzZmj82A1LH1nWeG3ipHpg/x4m6v3wEDvMBIKjRFUnfR3nBeFs3MVCr7UdAmg==} engines: {node: '>=22.12.0'} - '@commitlint/read@21.2.0': - resolution: {integrity: sha512-ELx8Ovh/JoAw5lpvDgxc6Y0We9skf2IPI2RFN+gnYgDGjRdMSF8zeodxhZmcclLWzfUIF7hXLOa8gOlllYcvBA==} + '@commitlint/read@21.2.1': + resolution: {integrity: sha512-hUW7EJQnNTL0vPOmVMNK4CrnrNBN0nN+JJHReFkdHO5y4iyHeEmTBwuC15OCqUTjxWo7idnH1LftfpWVIaPWIA==} engines: {node: '>=22.12.0'} - '@commitlint/resolve-extends@21.2.0': - resolution: {integrity: sha512-4O/1j51+79Wth9s/MGxt/5gs0XYLDgNlYpltQfhAvLE0itusLKs9zruxbiNg1oOkmkb9L9L4USYGjEj7n87NxA==} + '@commitlint/resolve-extends@21.2.2': + resolution: {integrity: sha512-RPkJ/IFi7sMUUVbZLqwWFtWw/zRDcfFsmrPSiTMrt5wb7AdxOr86EGQFvmGzef5QKV5IPBWWCujqVTw1RWX44A==} engines: {node: '>=22.12.0'} - '@commitlint/rules@21.2.0': - resolution: {integrity: sha512-C2yXMNpiB8ETZKfx5JD8+ExgF8vTU1VQMKPSUUYwqKpw9oJWQBrlXBpdU038mj2WPjof7o9UzFpmTyBeGMZwZg==} + '@commitlint/rules@21.2.2': + resolution: {integrity: sha512-eplQzyYkBjYB1HyyRj8hkcK11Y9DU9nuBz7uOKEd6NpE9NGDytLFCAnlRE+OoiK/5sHEJsaz2RGhuWBvYzIbNA==} engines: {node: '>=22.12.0'} '@commitlint/to-lines@21.0.1': @@ -1150,8 +1129,20 @@ packages: conventional-commits-parser: optional: true - '@conventional-changelog/template@1.2.0': - resolution: {integrity: sha512-12qHxvlKjHmP0PQ+17EREgC7lWyLwbph1RKcZQZ7k7ZWGmrxfxC9gadHGfvzr0g0u8BhiBGg3tks93txodlyRQ==} + '@conventional-changelog/git-client@3.1.2': + resolution: {integrity: sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==} + engines: {node: '>=22'} + peerDependencies: + conventional-commits-filter: ^6.0.1 + conventional-commits-parser: ^7.1.2 + peerDependenciesMeta: + conventional-commits-filter: + optional: true + conventional-commits-parser: + optional: true + + '@conventional-changelog/template@1.4.0': + resolution: {integrity: sha512-aalGyl7dbB5PArRebDIX43ZvBlXrYm9uWzGJ26t+4SzJVPsOuvfILGGbw5X4yX7i50YEmJ8zvbiWnqH/AAnZqg==} engines: {node: '>=22'} '@dprint/formatter@0.5.1': @@ -1172,8 +1163,8 @@ packages: '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -1186,8 +1177,8 @@ packages: resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.6.0': - resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/core@1.2.1': @@ -1247,23 +1238,10 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@inquirer/ansi@1.0.2': - resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} - engines: {node: '>=18'} - '@inquirer/ansi@2.0.7': resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/checkbox@4.3.2': - resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/checkbox@5.2.1': resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1273,15 +1251,6 @@ packages: '@types/node': optional: true - '@inquirer/confirm@5.1.21': - resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/confirm@6.1.1': resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1291,15 +1260,6 @@ packages: '@types/node': optional: true - '@inquirer/core@10.3.2': - resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/core@11.2.1': resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1309,15 +1269,6 @@ packages: '@types/node': optional: true - '@inquirer/editor@4.2.23': - resolution: {integrity: sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/editor@5.2.2': resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1327,15 +1278,6 @@ packages: '@types/node': optional: true - '@inquirer/expand@4.0.23': - resolution: {integrity: sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/expand@5.1.1': resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1345,15 +1287,6 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@1.0.3': - resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/external-editor@3.0.3': resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1363,23 +1296,10 @@ packages: '@types/node': optional: true - '@inquirer/figures@1.0.15': - resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} - engines: {node: '>=18'} - '@inquirer/figures@2.0.7': resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/input@4.3.1': - resolution: {integrity: sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/input@5.1.2': resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1389,15 +1309,6 @@ packages: '@types/node': optional: true - '@inquirer/number@3.0.23': - resolution: {integrity: sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/number@4.1.1': resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1407,15 +1318,6 @@ packages: '@types/node': optional: true - '@inquirer/password@4.0.23': - resolution: {integrity: sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/password@5.1.1': resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1425,15 +1327,6 @@ packages: '@types/node': optional: true - '@inquirer/prompts@7.10.1': - resolution: {integrity: sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/prompts@8.5.2': resolution: {integrity: sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1443,15 +1336,6 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@4.1.11': - resolution: {integrity: sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/rawlist@5.3.1': resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1461,15 +1345,6 @@ packages: '@types/node': optional: true - '@inquirer/search@3.2.2': - resolution: {integrity: sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/search@4.2.1': resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1479,15 +1354,6 @@ packages: '@types/node': optional: true - '@inquirer/select@4.4.2': - resolution: {integrity: sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/select@5.2.1': resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1497,15 +1363,6 @@ packages: '@types/node': optional: true - '@inquirer/type@3.0.10': - resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/type@4.0.7': resolution: {integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} @@ -1537,11 +1394,13 @@ packages: engines: {node: '>=18'} hasBin: true - '@microsoft/api-extractor-model@7.33.8': - resolution: {integrity: sha512-aIcoQggPyer3B6Ze3usz0YWC/oBwUHfRH5ETUsr+oT2BRA6SfTJl7IKPcPZkX4UR+PohowzW4uMxsvjrn8vm+w==} + '@microsoft/api-extractor-model@7.33.11': + resolution: {integrity: sha512-iDu1AtuRC2Z8XVs2SieZieVavF1FXPBX1C9pMexJh8Dx/Dd/3ZZ4nRQp/PU2Vk2rUHWuBz1wOyL4DcuhVnBXwg==} + engines: {node: '>=20.9.0'} - '@microsoft/api-extractor@7.58.9': - resolution: {integrity: sha512-S2UF4yza5GoxCmf7hJQNxJNZN9ltOVuOQv8Dy+Z21aol5ERoBNMdWcQHm4MJMPPItW4H/4rZD906iaf4mUojJA==} + '@microsoft/api-extractor@7.59.0': + resolution: {integrity: sha512-KDYV8kSVjmG8JJWVg1f1aKxteNG1IQ44D07Rjhlcci8wlqrSFNhUfgv7dJhwT0W2h3NDIL5Vz2f+/DfO4OpDHw==} + engines: {node: '>=20.9.0'} hasBin: true '@microsoft/tsdoc-config@0.18.1': @@ -1561,32 +1420,37 @@ packages: resolution: {integrity: sha512-aXFw1PGS8NmSEGAIJ1g5X+0kAiaWYPOvxkLttmKR1qO95O17mcpkKXfTdoSIyFnqPF2YnZjq9KR7Cvs27fNewg==} engines: {node: '25'} - '@nanoforge-dev/cli@1.6.0': - resolution: {integrity: sha512-hR2y1O4kvnj1nv6lNlInzdZdAhJEZ8U69EBo0mzncCPbIp6Icp5rEpjBLQERux56vVd2FSfGVNed7lOwUQ3RSg==} + '@nanoforge-dev/cli@1.6.2': + resolution: {integrity: sha512-BtjWOu6cX7A3sk256cCNA+wyem9oobzhfjg4/7tNt/zN1vLYTb5is3s+D5IRRG6M1ZovW0W1InN53ss5boBxVQ==} engines: {node: '25'} hasBin: true - '@nanoforge-dev/loader-client@1.3.0': - resolution: {integrity: sha512-qD3mJ/IOo7Nq3ru4q4yxW0DRIIk2uS/+rwYO9GWJcUVodlJumbSmVrTAoZnnI6lKki2MsKp9RtJJwPB2vNlOXQ==} + '@nanoforge-dev/editor@0.1.4': + resolution: {integrity: sha512-bqbrH8ulFSiZz1iisJHtHeEzj1RV/70uErCYHeW4DIhVPsWbBfWKFvg/ghAbmPk5vsj0YnhDX6DSpik4S1QoiQ==} + engines: {node: '25'} + + '@nanoforge-dev/loader-client@1.4.0': + resolution: {integrity: sha512-YYE41uqp/7+IXRXLi71UuWFBUXf8ZguMf32A/8qzCmbQN+gUtBdTKLwm+2VVcvih6mueCQCGnulH9t5SmC8+Qg==} engines: {node: '25'} - '@nanoforge-dev/loader-server@1.2.0': - resolution: {integrity: sha512-Fc209YxN2E5uU1P33u+Tr0GM0AoRG27Y7dDxXbTn285nzC2ePP4gVHdws+wE11CY54TnisWhjCislq5EIFxNgQ==} + '@nanoforge-dev/loader-server@1.4.0': + resolution: {integrity: sha512-jvNoHxx54BAfjUTMZHb/T/8ApbdPV/NNGwiQITUBprH4Uv8jQmbR7zNB5Z6/vIEjSVVxrU0b4fFa+BkdnKX/iQ==} engines: {node: '25'} - '@nanoforge-dev/loader-website@1.2.0': - resolution: {integrity: sha512-gKFEQFt1+RIQyRzpVyjuaXib4nBLa4g3LNfy9TEMPlXe21IZy346L3RO5PmlVslPAYJuy5chUXfBE+BmE9BedA==} + '@nanoforge-dev/loader-website@1.4.0': + resolution: {integrity: sha512-+5el/zkSJQL9qCd+4a6fGpIDMQi26QRTWXJ24mJFMaDC74P1lvqnes0u0l0+/s9dunJxfgea0Epse0/Jj/3M3Q==} engines: {node: '25'} - '@nanoforge-dev/schematics@2.1.3': - resolution: {integrity: sha512-5o4z+GTQF/dzvkk6UrwtoUrlrjFWQBevvtupCqc0coiLfetU2FUORryFPG1tZhrIP3GPuuYTM/8meTJDs7IMPA==} + '@nanoforge-dev/schematics@2.2.1': + resolution: {integrity: sha512-MdmhFncakgejGRIf1HTPKTskhdv8bIst21uWRSZCXGgGv0UNYEfDiziOsWPVCzGc9dXei59RIDznBwgpAMeXLg==} engines: {node: '25'} - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 '@octokit/auth-token@6.0.0': resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} @@ -1596,17 +1460,32 @@ packages: resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} engines: {node: '>= 20'} + '@octokit/core@7.0.7': + resolution: {integrity: sha512-DcB0M3KFgr9ECI328lhBMVsyFT2DnmNucSBTqEN3exyNKUzkkpUSCHmTRcunF41Eou2TIQKW4seewri8ON9bSA==} + engines: {node: '>= 20'} + '@octokit/endpoint@11.0.3': resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} engines: {node: '>= 20'} + '@octokit/endpoint@11.0.4': + resolution: {integrity: sha512-f1cOWoHPmxryJFknxbtDdjODWfV8A9tc8Aae6ermXPNgHFZ/x91AtHIz4gicEjL8hkJiip+u21QHJORfBv/qiA==} + engines: {node: '>= 20'} + '@octokit/graphql@9.0.3': resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==} engines: {node: '>= 20'} + '@octokit/graphql@9.0.4': + resolution: {integrity: sha512-5s15CCiY8XXQ+FG+b1YQcl6Z2FA++nwAz/tg2VUrTmnMncP+2nnGUEYANImdnxsA2Fnq+Mbl7hDjUTw7cFAwcg==} + engines: {node: '>= 20'} + '@octokit/openapi-types@27.0.0': resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==} + '@octokit/openapi-types@28.0.0': + resolution: {integrity: sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==} + '@octokit/plugin-paginate-rest@14.0.0': resolution: {integrity: sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==} engines: {node: '>= 20'} @@ -1629,17 +1508,24 @@ packages: resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} engines: {node: '>= 20'} + '@octokit/request-error@7.1.1': + resolution: {integrity: sha512-+eaY7G2VVpSf2pc5Gn1+mph837V/d/TYTJAgWL9Tb0ogGYcpN3IlAVFgjL+Vv93F/sevrxkvsYCedtpLdcFLzA==} + engines: {node: '>= 20'} + '@octokit/request@10.0.10': resolution: {integrity: sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w==} engines: {node: '>= 20'} - '@octokit/request@10.0.11': - resolution: {integrity: sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q==} + '@octokit/request@10.0.15': + resolution: {integrity: sha512-3CBg9aJ0hO9Pjyij8LbK/xYtEaPws9SW7xKz67daPNxQB1q5Y9OMA7DDOG0A6Hwf9ygGu3tvzusg0LXQ8/wAjA==} engines: {node: '>= 20'} '@octokit/types@16.0.0': resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} + '@octokit/types@17.0.0': + resolution: {integrity: sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==} + '@oven/bun-darwin-aarch64@1.3.14': resolution: {integrity: sha512-Omj20SuiHBOUjUBIyqtkNjSUIjOtEOJwmbix/ZyFH4BaQ6OZTaaRWIR4TjHVz0yadHgli6lLTiAh1uarnvD49A==} cpu: [arm64] @@ -1720,8 +1606,11 @@ packages: cpu: [x64] os: [win32] - '@oxc-project/types@0.137.0': - resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + '@oxc-project/types@0.147.0': + resolution: {integrity: sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==} '@oxfmt/binding-android-arm-eabi@0.35.0': resolution: {integrity: sha512-BaRKlM3DyG81y/xWTsE6gZiv89F/3pHe2BqX2H4JbiB8HNVlWWtplzgATAE5IDSdwChdeuWLDTQzJ92Lglw3ZA==} @@ -1852,97 +1741,193 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@rolldown/binding-android-arm64@1.1.3': - resolution: {integrity: sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==} + '@rolldown/binding-android-arm-eabi@1.2.6': + resolution: {integrity: sha512-b+jTcARdTiFLI6jB4a5XjTm0RWd6KcRfQj/I2356fxUZemiho9zQLxo0RtCuMDAyKcLo6cEltkgbQp6d1+sjjQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-android-arm64@1.2.6': + resolution: {integrity: sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.3': - resolution: {integrity: sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==} + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-arm64@1.2.6': + resolution: {integrity: sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.3': - resolution: {integrity: sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==} + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.6': + resolution: {integrity: sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.3': - resolution: {integrity: sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==} + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-freebsd-x64@1.2.6': + resolution: {integrity: sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.3': - resolution: {integrity: sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.6': + resolution: {integrity: sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.3': - resolution: {integrity: sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==} + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-gnu@1.2.6': + resolution: {integrity: sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.1.3': - resolution: {integrity: sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==} + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-arm64-musl@1.2.6': + resolution: {integrity: sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.1.3': - resolution: {integrity: sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==} + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-ppc64-gnu@1.2.6': + resolution: {integrity: sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.1.3': - resolution: {integrity: sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==} + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.2.6': + resolution: {integrity: sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.1.3': - resolution: {integrity: sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==} + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.2.6': + resolution: {integrity: sha512-KekI0gS0wLxe1UBSQSjenBVwou/JkcQPDzBPICGZjxUv9k3RteHDPBQaiOicZUFKRIH2wKEimGwVpnJsbPzu7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.1.3': - resolution: {integrity: sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==} + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.1.3': - resolution: {integrity: sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==} + '@rolldown/binding-linux-x64-musl@1.2.6': + resolution: {integrity: sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-openharmony-arm64@1.2.6': + resolution: {integrity: sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.3': - resolution: {integrity: sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==} + '@rolldown/binding-wasm32-wasi@1.1.5': + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.1.3': - resolution: {integrity: sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==} + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-arm64-msvc@1.2.6': + resolution: {integrity: sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.3': - resolution: {integrity: sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==} + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.6': + resolution: {integrity: sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1958,8 +1943,9 @@ packages: '@types/node': optional: true - '@rushstack/node-core-library@5.23.1': - resolution: {integrity: sha512-wlKmIKIYCKuCASbITvOxLZXepPbwXvrv7S6ig6XNWFchSyhL/E2txmVXspHY49Wu2dzf7nI27a2k/yV5BA3EiA==} + '@rushstack/node-core-library@5.24.0': + resolution: {integrity: sha512-g/Z47ZwARn/VkTnHcyJslrR26erRf1G5JbqPlfGZGBCrOcrEt8fTQXXDVhUDDNl/g/v3TXI1dNiAAT5FEks8BA==} + engines: {node: '>=20.9.0'} peerDependencies: '@types/node': '*' peerDependenciesMeta: @@ -1993,16 +1979,18 @@ packages: '@types/node': optional: true - '@rushstack/terminal@0.24.0': - resolution: {integrity: sha512-8ZQS4MMaGsv27EXCBiH7WMPkRZrffeDoIevs6z9TM5dzqiY6+Hn4evfK/G+gvgBTjfvfkHIZPQQmalmI2sM4TQ==} + '@rushstack/terminal@0.24.3': + resolution: {integrity: sha512-KxphDhPGC4xDrKg8O4yrWCEpPMi87aJc1iycXqMVh1dLgV0M34hiH9ZTgWjBRmcrT/OIHoOeWf48npcQFzgp+g==} + engines: {node: '>=20.9.0'} peerDependencies: '@types/node': '*' peerDependenciesMeta: '@types/node': optional: true - '@rushstack/ts-command-line@5.3.10': - resolution: {integrity: sha512-fwI076HYknC0IrMXdY6UmjDv+PH7NHhNJX3/pY2UblSE5XrXgndXZPiOe/6ZtuFpn6DvVDVNhtkIzQ+Qu/MhVQ==} + '@rushstack/ts-command-line@5.3.13': + resolution: {integrity: sha512-+jNbxhh8CkrZYxMk9X3GRYM2+Myr1xCCj+eHbJ9Vp+PCdNHS0TUl5QQFT6UbM/aTFRCzs5jiBTKYzBRpe5uYbQ==} + engines: {node: '>=20.9.0'} '@sapphire/result@2.8.0': resolution: {integrity: sha512-693yWouX+hR9uJm1Jgq0uSSjbSD3UrblMaxiuGbHPjSwzLCSZTcm0h3kvdVhq3o/yl4+oeAWW3hiaJ0TELuRJQ==} @@ -2019,6 +2007,10 @@ packages: resolution: {integrity: sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==} engines: {node: '>=18'} + '@simple-libs/child-process-utils@2.0.0': + resolution: {integrity: sha512-dvNoRKLijXnD0XoJAz94pbNuB5GQgDr55UhpSPhffDkTT0Cmcqh9jSCOtwfT2d4H6MI9E7c4SgtMuJXZ6F3c6A==} + engines: {node: '>=22'} + '@simple-libs/stream-utils@1.2.0': resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} engines: {node: '>=18'} @@ -2038,14 +2030,14 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@tanstack/react-virtual@3.14.5': - resolution: {integrity: sha512-4EKRXh7zBLkbKbFmG3AUVkircuHd+7OdT1pocJSepxtfBd3qnrJgJ5rtPkRYyo9fmyVb2+pI2xPy5oYvMLQy6A==} + '@tanstack/react-virtual@3.14.10': + resolution: {integrity: sha512-SRyoUbdFMRHuYXMijV5H4ZarQWpXkj3iANq8OFre+pybeVap8ZJjZ3Nz9bVjx4d8PfobVUQUdKyyyHYk3E+djw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/virtual-core@3.17.3': - resolution: {integrity: sha512-8Np/TFELpI0ySuJoVmjvOrQYXH/8sTX0Biv9szhFhY39xOdAAY+smrMxjxOum/ux3eM8MUJQsEJ0/R0UpvC8dw==} + '@tanstack/virtual-core@3.17.8': + resolution: {integrity: sha512-BfEvehNpOT75r5Ksc5xW6NZuXujTfb7nlSEyVu4XHG3gdxNg1KqXruWbDewXOUaUYIo4oRbSfkjIajz4MAT8tA==} '@trivago/prettier-plugin-sort-imports@6.0.2': resolution: {integrity: sha512-3DgfkukFyC/sE/VuYjaUUWoFfuVjPK55vOFDsxD56XXynFMCZDYFogH2l/hDfOsQAm1myoU/1xByJ3tWqtulXA==} @@ -2066,33 +2058,33 @@ packages: svelte: optional: true - '@turbo/darwin-64@2.10.1': - resolution: {integrity: sha512-EjfrTXVmT0r4Spv+nu1KRcvjqavCq35F5GRCvoxQi83uoX3wxQ2QTgDkSxO8O4HVXyi28dW0of/y2RFBOD4emA==} + '@turbo/darwin-64@2.10.12': + resolution: {integrity: sha512-9nKgKoF6ZOUsM+or0OtNf+TTJSfGvDNP7ZFv/ZGWVwOSCkumyctQiTeHwB4UNljHTnC41AqylgbunLDHoccNrA==} cpu: [x64] os: [darwin] - '@turbo/darwin-arm64@2.10.1': - resolution: {integrity: sha512-nVNvaJ7aHxF5zBw8Nc9Er2Iw8A/SPAw25sqlu/63/qGfDMGdarRYrxjdM0O0XK8X8bGg3Yr93Ro7I5tJksrfgA==} + '@turbo/darwin-arm64@2.10.12': + resolution: {integrity: sha512-H4Elb1jqTZVeIC9bbcNwjSzemZ6RegoTOVHeuV5Osirt2Z8UguTyisMEkvZjPVZgMeN9J4ERZBFad40tFnkb7w==} cpu: [arm64] os: [darwin] - '@turbo/linux-64@2.10.1': - resolution: {integrity: sha512-jaYr5GQGfW2jMkoux7/Yh+pUhKgqBM0pyAZnNTUybnVPy4qB2jP0C4B32Nmg00BYaAU3FaWr/bQ3CKKIYjdI2Q==} + '@turbo/linux-64@2.10.12': + resolution: {integrity: sha512-lr7KIotukvjZwEXiFSYAeOH3BWzjFVBbSzTbv0fuGFsNukYyH0+g1hB5ecqnJkgkYU+KHEMG1edOhnjiKON1wQ==} cpu: [x64] - os: [linux] + os: [android, linux] - '@turbo/linux-arm64@2.10.1': - resolution: {integrity: sha512-2Wg5TBGYQjaPMJhQzYf0EEM9N5mSE3AKmWBWKz6fsjZ8dlLL4uV7X3PnwtNO1+kRYjwg34ilJwweaT8MvxZOcA==} + '@turbo/linux-arm64@2.10.12': + resolution: {integrity: sha512-f0pZDTtvzB5SuNwuXBaKbZHUCMCukgc8nMlHEuvLmj91Fzec+MEbr3cAvGNor5htEDqZnO6Lxt9N/GPI/77oGA==} cpu: [arm64] - os: [linux] + os: [android, linux] - '@turbo/windows-64@2.10.1': - resolution: {integrity: sha512-fRCK6wZiWQgE5fb+WpaBgDsHNo/fKcCoMEOms9E5Il/Bp/ec9uhsVNn0V/2gmN2hSCyFm7oKf0BZY6Lb6CDMOQ==} + '@turbo/windows-64@2.10.12': + resolution: {integrity: sha512-SDOueJRjS/QcykWf2KCRtTLmIl5YMKsLbXkXQGhDwcTXvKXZiS5ih5lBl/gkwZIpYFjqA/rAlfMzlAFcVHNe0g==} cpu: [x64] os: [win32] - '@turbo/windows-arm64@2.10.1': - resolution: {integrity: sha512-6REIwRpmmnJdHYL+fIv2BGBC9PYd+8Ta+J53nmcHjqi46v/z+hS1sirYU5fg7Cg1r9/99dpRtSXHKTgvcLYSpg==} + '@turbo/windows-arm64@2.10.12': + resolution: {integrity: sha512-0i0mVUa4kKk+/B3RwEwPMf9CB+T7ul56hn5FFHNA4VUNTOoLBEd6aNf3FaKfCatDNZ6cicCEf6if9QUTVyzzcA==} cpu: [arm64] os: [win32] @@ -2117,14 +2109,11 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/jsesc@2.5.1': - resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@26.0.1': - resolution: {integrity: sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==} + '@types/node@26.4.0': + resolution: {integrity: sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==} '@types/validator@13.15.10': resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} @@ -2191,67 +2180,322 @@ packages: resolution: {integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitest/coverage-v8@4.1.9': - resolution: {integrity: sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==} - peerDependencies: - '@vitest/browser': 4.1.9 - vitest: 4.1.9 - peerDependenciesMeta: - '@vitest/browser': - optional: true + '@typescript/typescript-aix-ppc64@7.0.2': + resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [aix] - '@vitest/expect@4.1.9': - resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} + '@typescript/typescript-darwin-arm64@7.0.2': + resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [darwin] - '@vitest/mocker@4.1.9': - resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true + '@typescript/typescript-darwin-x64@7.0.2': + resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [darwin] - '@vitest/pretty-format@4.1.9': - resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} + '@typescript/typescript-freebsd-arm64@7.0.2': + resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [freebsd] - '@vitest/runner@4.1.9': - resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} + '@typescript/typescript-freebsd-x64@7.0.2': + resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [freebsd] - '@vitest/snapshot@4.1.9': - resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} + '@typescript/typescript-linux-arm64@7.0.2': + resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [linux] - '@vitest/spy@4.1.9': - resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} + '@typescript/typescript-linux-arm@7.0.2': + resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} + engines: {node: '>=16.20.0'} + cpu: [arm] + os: [linux] - '@vitest/utils@4.1.9': - resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} + '@typescript/typescript-linux-loong64@7.0.2': + resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} + engines: {node: '>=16.20.0'} + cpu: [loong64] + os: [linux] - abbrev@3.0.1: - resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} - engines: {node: ^18.17.0 || >=20.5.0} + '@typescript/typescript-linux-mips64el@7.0.2': + resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} + engines: {node: '>=16.20.0'} + cpu: [mips64el] + os: [linux] - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript/typescript-linux-ppc64@7.0.2': + resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [linux] - acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} - engines: {node: '>=0.4.0'} - hasBin: true + '@typescript/typescript-linux-riscv64@7.0.2': + resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} + engines: {node: '>=16.20.0'} + cpu: [riscv64] + os: [linux] - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} + '@typescript/typescript-linux-s390x@7.0.2': + resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} + engines: {node: '>=16.20.0'} + cpu: [s390x] + os: [linux] - ajv-draft-04@1.0.0: - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: + '@typescript/typescript-linux-x64@7.0.2': + resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [linux] + + '@typescript/typescript-netbsd-arm64@7.0.2': + resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [netbsd] + + '@typescript/typescript-netbsd-x64@7.0.2': + resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [netbsd] + + '@typescript/typescript-openbsd-arm64@7.0.2': + resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [openbsd] + + '@typescript/typescript-openbsd-x64@7.0.2': + resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [openbsd] + + '@typescript/typescript-sunos-x64@7.0.2': + resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [sunos] + + '@typescript/typescript-win32-arm64@7.0.2': + resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [win32] + + '@typescript/typescript-win32-x64@7.0.2': + resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [win32] + + '@vitest/coverage-v8@4.1.11': + resolution: {integrity: sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==} + peerDependencies: + '@vitest/browser': 4.1.11 + vitest: 4.1.11 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@4.1.11': + resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + + '@vitest/mocker@4.1.11': + resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.11': + resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} + + '@vitest/runner@4.1.11': + resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} + + '@vitest/snapshot@4.1.11': + resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} + + '@vitest/spy@4.1.11': + resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} + + '@vitest/utils@4.1.11': + resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + + '@yuku-codegen/binding-android-arm64@0.8.7': + resolution: {integrity: sha512-C/0zV5IhgVdYhGJTwrY0v8dknxlhiKwtVJkMUaexu9/QvRmzlV4vfU3hZlUSgqc2BxQHntL1mCVbDq8j0FRFDw==} + cpu: [arm64] + os: [android] + + '@yuku-codegen/binding-darwin-arm64@0.8.7': + resolution: {integrity: sha512-/u+REDMI4a0/lsJXTM4c53/w31OGZLOReZIyg62uhgLs0kc8NHsj/nOcxTdlQjq5gi0zhdkccD9LaLTXcdzPvw==} + cpu: [arm64] + os: [darwin] + + '@yuku-codegen/binding-darwin-x64@0.8.7': + resolution: {integrity: sha512-sMMzFOwCo4WXR+/6zIBThOocSC50iIIZZdfiIDbaLvj0Ax/rWt/iavyfEAqajyvzydLyCqR/ZItdLWSRlu1umw==} + cpu: [x64] + os: [darwin] + + '@yuku-codegen/binding-freebsd-x64@0.8.7': + resolution: {integrity: sha512-MpdpKXix9P+Y1rKgjvcNeNtGjXeL1CmttNhYINrWls8kRpm4xM/oBGTmn6w7to8lAlwj5jm8q03dQPl5mRv4Qw==} + cpu: [x64] + os: [freebsd] + + '@yuku-codegen/binding-linux-arm-gnu@0.8.7': + resolution: {integrity: sha512-rr1srFLlPAmC1vtxfc9C1YLDe3iH09YjfSeeIidBqKhzx1MATjOAq4mjlRUOnhr/L27MotWIYOFKwVsd5JZFOg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm-musl@0.8.7': + resolution: {integrity: sha512-eAufXh8qBRpiSO6ueaMDL+yyoXIGLhpUce72YbcACtZU2qhExwBIJyEtQf5kH2Ki0X2aqkSjSfog4OPtKXan3Q==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-arm64-gnu@0.8.7': + resolution: {integrity: sha512-gw4w6wPoHObBrdIC4duVWLmJOvpdE25j5D7yrM5mACNlK4klRz/lv8hK+ssQk9EJHBgZjSaqZIJVFgqNYbfv7A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm64-musl@0.8.7': + resolution: {integrity: sha512-L68N6Y4XkqcIaKo3Ra88JEvBEH4AHff44A4INcrxeVWZ8CZtu2tCpfVxe3hR8qQQMcvBSQlDn24KpkCKEhVvfA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-x64-gnu@0.8.7': + resolution: {integrity: sha512-dzyAbltJmf3Cqlb8HcFuYIf5Yn0fl1vTr3XJ9HiVNNvOlhqPSArOqtw9vI1p6/VTXTjrMLXlU+s+/kNHiIy/Cw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-x64-musl@0.8.7': + resolution: {integrity: sha512-Otw4MH3404q0Bbvl+YTdW9aoUV5vXmUw8260bWvt1XlaoIX/ceSgI4ygheRDMfBPoHt6FDayQaO9OLVUZAgkFA==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-win32-arm64@0.8.7': + resolution: {integrity: sha512-qo/jyrzryiBuKEsFiuWaBCBe3tRMynQ0qFWFgOEjcCMQeZfBm+wKiVEUEFXXLc7bh8YezguAWp0Mtnhq4ARNyA==} + cpu: [arm64] + os: [win32] + + '@yuku-codegen/binding-win32-x64@0.8.7': + resolution: {integrity: sha512-D5lDsVDx6m00E6bWySlWdH72Ca4TPSaphDqB6QjU6MpuNLIJqoGoatYyq2rOmBE8Zv/kunot/o58KGL03P3eiA==} + cpu: [x64] + os: [win32] + + '@yuku-parser/binding-android-arm64@0.8.7': + resolution: {integrity: sha512-eGKYiUDX7Y0V7tDTmg+JTVnXnjMqfXXsorZ+EDf5kxwchQ3Or1HS14MzI2fw+jFhHR85fCWt+mtX33Yao73hIQ==} + cpu: [arm64] + os: [android] + + '@yuku-parser/binding-darwin-arm64@0.8.7': + resolution: {integrity: sha512-Re0RHelKLnjEURulY2/KxW+Ngb8zuNA4BRZuMwgGQNzVumT6u4U2N2hc01oeYVNVof0i7GrXE4UCNBgbpRRnjQ==} + cpu: [arm64] + os: [darwin] + + '@yuku-parser/binding-darwin-x64@0.8.7': + resolution: {integrity: sha512-Hn8DROtQkjlA1ACbPgj4a7eP9IuVOI504oiTwpkWPbpaDWD9KdmnVYCqW+1LfenNK/g7O9NhWGpXEdaCNX7lIA==} + cpu: [x64] + os: [darwin] + + '@yuku-parser/binding-freebsd-x64@0.8.7': + resolution: {integrity: sha512-bAP2OV8wRuzplX/jYxv9+vvqQT8JxyNphI8fLfXGL054Xs+4/J5u33cIm3y4rxY8rdoLmmdiJs2Tq7r7lrDRfA==} + cpu: [x64] + os: [freebsd] + + '@yuku-parser/binding-linux-arm-gnu@0.8.7': + resolution: {integrity: sha512-kTYwJQQgmZeAWdDIWabiReIZMpmfLueIj1tCmjStUtFGhR1Z0qwxonKVfUC4N7h/VhGGzLZ//7O1kgt1QKqgCg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm-musl@0.8.7': + resolution: {integrity: sha512-uL4jE8HPT2BLlxAXyD10LqgPuXa9eDa0BKpCdSANmzIJghq/2eZo3/gQNtaxPZMupWoxjYzSad9IXrwu7aYPXQ==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-arm64-gnu@0.8.7': + resolution: {integrity: sha512-3gVN4pWSKZmXiNX7cU164dR9MPvesCHnlH6nPfpK+yQsCuYphjKKplcb4SnZBrhiqmXbgb2HR0c2TS0IZUPhgA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm64-musl@0.8.7': + resolution: {integrity: sha512-S0mwfEjoLpxzXeZw802Wa4RaELsQiPtWqG6INcy8j4GtvNFtl4LCX3eGO1XLn9pyLAISLzTRyU3zUCBUPin8lg==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-x64-gnu@0.8.7': + resolution: {integrity: sha512-lnbWdPmerE5D1uH1G4IEZKnPzCrWCStRGrtgpSIe1RibAo5bZIjDbbbPYXmMHCEh4F+x/JaJpElh26a3r+BPbg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-x64-musl@0.8.7': + resolution: {integrity: sha512-769uwndMvMzUvATWbAcEvyLHKA+DzhHSCl/obBUrRdYfRo26yxui6S8y3z7uJ+Naup7UKrDxrpK7OnQkxkl9KQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-win32-arm64@0.8.7': + resolution: {integrity: sha512-mEB/9PlaAkisJ6KWGz0zvywXoU6+80dTlR2LwS7s/jcXXoU6fm2+sitBZXtqu3+Q4DcDgPxM45uWMCzPs0TSRw==} + cpu: [arm64] + os: [win32] + + '@yuku-parser/binding-win32-x64@0.8.7': + resolution: {integrity: sha512-8vNB2DP0ou61nGb8tc/qfi41gfyDXz1MHr2zqL3nR+cJ6CEbiuWV/l/a/vv151gCgiZLLAyGkQGENpozdg716w==} + cpu: [x64] + os: [win32] + + '@yuku-toolchain/types@0.8.7': + resolution: {integrity: sha512-2Z53dNxAJL6UvFoIrDZvYf3zlO8s4VJK4O2hhaB4mXVwwpX/7ajtss3cmfqKvamlNLWyt9FSWs4eoYdlbxpnHA==} + + abbrev@3.0.1: + resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} + engines: {node: ^18.17.0 || >=20.5.0} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: ajv: optional: true @@ -2287,10 +2531,6 @@ packages: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} @@ -2305,6 +2545,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + argue-cli@3.1.0: + resolution: {integrity: sha512-DhBpBfXL4SS2uC0N922MMajKR3CdrTG0u2or1PNYgXMsrSzViJrbtvT0nCLlLGUI0plam/ZZCs7aAauHtW9thw==} + engines: {node: '>=22'} + assert@2.1.0: resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} @@ -2312,12 +2556,8 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - ast-kit@3.0.0: - resolution: {integrity: sha512-8OG92q3R35qjC/4i6BLBMg8IB+fClWu/1PEwg2Z9Rn+BuNaiEgJzpzn+pxWOdHJWDCAwu2JP0wCDTozAM4QirQ==} - engines: {node: ^22.18.0 || >=24.11.0} - - ast-v8-to-istanbul@1.0.4: - resolution: {integrity: sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA==} + ast-v8-to-istanbul@1.0.5: + resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==} async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} @@ -2336,18 +2576,19 @@ packages: before-after-hook@4.0.0: resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} - birpc@4.0.0: - resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} - bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - brace-expansion@2.1.1: - resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} - brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} bun@1.3.14: resolution: {integrity: sha512-aB6GVd42x1Y5ie1K16SF+oLGtgSkwX9hgoDdIW88pjvfTccU8F1vfpoOt34QLv0dZ1v3XimtaxPlZUG81Gx9Zg==} @@ -2423,10 +2664,6 @@ packages: resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} - engines: {node: '>=20'} - cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} @@ -2446,13 +2683,6 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -2476,12 +2706,16 @@ packages: resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} engines: {node: '>=18'} - conventional-changelog-angular@9.2.0: - resolution: {integrity: sha512-2EihZvM1KmbBGwuUow8lNXLe+ECRFsyOcV8X0197/WI7Rvvgfi55Oicfw0wxJTXGGIVXSfj+xBoNj+cxLlIiVw==} + content-type@3.0.0: + resolution: {integrity: sha512-AIi5H6p0xk5uknXcN3/rmhP8jgp69OfSe/JuKiQAFprJ7UGw7mwj7m4XcmDzlrnJDG+cGpphAINGdU3g3g7kDw==} + engines: {node: '>=22'} + + conventional-changelog-angular@9.4.0: + resolution: {integrity: sha512-HdxRxuS8bBXVIuo4V82gvSwAXT0vYQUizrjs/izmPg5JdDstr8v8I5hduGL3iQbG+o310dUDxC4+LetuS5hu9w==} engines: {node: '>=22'} - conventional-changelog-conventionalcommits@10.2.0: - resolution: {integrity: sha512-UtlM9GqolY7OmlQh5L/UEVoKsTUpTgUVy1PU8JN5gl5Ydaejb7WRklGliG1SKPxxj7hzA173eG3Kt5fYWE2pmg==} + conventional-changelog-conventionalcommits@10.4.0: + resolution: {integrity: sha512-Rriac6ZrAlVm6cy9Bz4NSp+WMHpwNXoPIYex+HjCgduAVUSbnew29DQjQw0C4g9u3HtSYzGiGY+pdBXAZo+4aA==} engines: {node: '>=22'} conventional-changelog-preset-loader@5.0.0: @@ -2497,8 +2731,8 @@ packages: engines: {node: '>=18'} hasBin: true - conventional-commits-parser@7.0.0: - resolution: {integrity: sha512-dZe/p+FgGQLNJFqaCgNdl8j6a7gI8xuaN30Wy5g7nvyK3jqOpNUEUZ3pGJ5D68h89uRh038FtkeOk/bnGmYkmg==} + conventional-commits-parser@7.1.2: + resolution: {integrity: sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==} engines: {node: '>=22'} hasBin: true @@ -2635,15 +2869,15 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.2.0: - resolution: {integrity: sha512-3lGxdTXCLfe1MYfTz1y2ksAAUM4NAOP6rPEjxGJVKO7TZ5+tvHCaQWGpC4Y3IXvW3ece0Cz1cIP4FWBxOnGCTQ==} + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} - es-toolkit@1.49.0: - resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + es-toolkit@1.51.0: + resolution: {integrity: sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==} escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} @@ -2705,8 +2939,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.6.0: - resolution: {integrity: sha512-6lVbcqSodALYo+4ELD0heG6lFiFxnLMuLkiMi2qV8LMp54N8tE8FT1GMH+ev4Ti00nFjNze2+Su6DsV5OQW3Dg==} + eslint@10.9.1: + resolution: {integrity: sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -2738,9 +2972,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - eventemitter3@5.0.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - execa@9.6.1: resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} @@ -2767,8 +2998,8 @@ packages: fast-string-width@3.0.2: resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} - fast-uri@3.1.3: - resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} + fast-uri@3.1.6: + resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==} fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} @@ -2793,6 +3024,10 @@ packages: filelist@1.0.6: resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -2801,8 +3036,8 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} @@ -2883,12 +3118,6 @@ packages: engines: {node: ^18.19 || >=20.6} hasBin: true - git-raw-commits@5.0.1: - resolution: {integrity: sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==} - engines: {node: '>=18'} - deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. - hasBin: true - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -3021,10 +3250,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - is-generator-function@1.1.2: resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} @@ -3050,6 +3275,10 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -3114,6 +3343,10 @@ packages: resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} hasBin: true + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -3134,6 +3367,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-with-bigint@3.5.12: + resolution: {integrity: sha512-uwbF/wSSuOgC7qqlq27Xp5B6a2MHVug3t0idZdTqu0JnlFvgJuH7ju+KAk/J06C7GfhoYy2gnb9wz2INqcne7w==} + json-with-bigint@3.5.8: resolution: {integrity: sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==} @@ -3156,97 +3392,93 @@ packages: libphonenumber-js@1.13.7: resolution: {integrity: sha512-rvr3HIMdOgzhz1RFGjftji+wjoAFlzhqCNqJOU/MKTZQ8d9NZxAR/tI+0weDicyoucqVR0U1GCniqHJ0f8aM2A==} - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@17.0.8: - resolution: {integrity: sha512-B2P/d+jVW0UXOQ0MVMLrB/9ydA1P+zz6jYfdrbbEd9ur3S2rcbduFWKiUCC02Sm5hbC8nrm7y24WuYMG54HfxA==} + lint-staged@17.3.0: + resolution: {integrity: sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw==} engines: {node: '>=22.22.1'} hasBin: true - liquidjs@10.27.1: - resolution: {integrity: sha512-ylE+1q2kSef1UxAyxqbyuWM3FRWS1v48JK1Y3CoW3bD6TSNXZh0+GsVnihujEpKyR+Jejx2aRAFfC3AHm9rElg==} + liquidjs@10.29.0: + resolution: {integrity: sha512-pCVOhs6FLAR8su3ItJ07diN26t6W5dHQRnmTMy8HPyTFuv1+oSCVJIGp5pGjfQyOZfh50KswvKtMTp6p4JEIdw==} engines: {node: '>=16'} hasBin: true - listr2@10.2.2: - resolution: {integrity: sha512-JtNtbZj8q5BnDMR7trpwvwk3RIrANtIVzEUm8w7amp6xelLgyuq+4WZoTH913XaQAoH/cNdYhaNzBPA2U3xbDw==} - engines: {node: '>=22.13.0'} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -3261,10 +3493,6 @@ packages: resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} engines: {node: '>=18'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -3276,8 +3504,11 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.5.3: - resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} + magic-string@1.0.0: + resolution: {integrity: sha512-CGvjzMN08iv6w1mm4/x3Gh1hLb4VnyRUA15FFpl6CsCIGGoe36k7kY5KNz9QDbSBN5I/fWHM6ZlIkUTa5xdUEA==} + + magicast@0.5.4: + resolution: {integrity: sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -3291,9 +3522,9 @@ packages: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} - meow@14.1.0: - resolution: {integrity: sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==} - engines: {node: '>=20'} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} @@ -3303,8 +3534,8 @@ packages: resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==} engines: {node: 18 || 20 || >=22} - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} minimatch@5.1.9: @@ -3342,16 +3573,12 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mute-stream@2.0.0: - resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} - engines: {node: ^18.17.0 || >=20.5.0} - mute-stream@3.0.0: resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} engines: {node: ^20.17.0 || >=22.9.0} - nanoid@3.3.15: - resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -3392,8 +3619,8 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - obug@2.1.3: - resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} ohash@2.0.11: @@ -3411,10 +3638,6 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - ora@9.3.0: - resolution: {integrity: sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==} - engines: {node: '>=20'} - ora@9.4.1: resolution: {integrity: sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==} engines: {node: '>=20'} @@ -3471,8 +3694,16 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} plur@5.1.0: @@ -3483,8 +3714,8 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss@8.5.16: - resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} + postcss@8.5.26: + resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} engines: {node: ^10 || ^12 || >=14} powershell-utils@0.1.0: @@ -3499,13 +3730,8 @@ packages: resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} engines: {node: '>=6.0.0'} - prettier@3.9.1: - resolution: {integrity: sha512-ppiDo2CSwexck1eyZUwJHg/N3nf1+6IRCv7W/VJ5vaLnVCmB7+3CdRfMwoCHBBX6xTrREDTksZ4OZl5SSf4zXA==} - engines: {node: '>=14'} - hasBin: true - - prettier@3.9.4: - resolution: {integrity: sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg==} + prettier@3.9.6: + resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} engines: {node: '>=14'} hasBin: true @@ -3563,30 +3789,32 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rolldown-plugin-dts@0.26.0: - resolution: {integrity: sha512-e+kEPtUiDES0htk5iqkSeF4EzAV7R+vugGB44iPDuw1Kw9E+WyL1VG7PaV0IIjGHLiacztMBcMTyrr8ON9CT1Q==} + rolldown-plugin-dts@0.27.14: + resolution: {integrity: sha512-ZvuDDwoIpRK9RPxDXratCpklFO9QZZWndf/sd0VBFb4LEj0jj07UcHK9OCh7V4XiFz2Z89ziyBC2K6tJiDjrbw==} engines: {node: ^22.18.0 || >=24.11.0} peerDependencies: - '@ts-macro/tsc': ^0.3.6 - '@typescript/native-preview': '>=7.0.0-dev.20260325.1' + '@typescript/native-preview': '*' + '@volar/typescript': ~2.4.0 rolldown: ^1.0.0 - typescript: ^5.0.0 || ^6.0.0 + typescript: ^5.0.0 || ^6.0.0 || ~7.0.0 vue-tsc: ~3.2.0 || ~3.3.0 peerDependenciesMeta: - '@ts-macro/tsc': - optional: true '@typescript/native-preview': optional: true + '@volar/typescript': + optional: true typescript: optional: true vue-tsc: optional: true - rolldown@1.1.3: - resolution: {integrity: sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==} + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rolldown@1.2.6: + resolution: {integrity: sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -3648,14 +3876,6 @@ packages: resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} engines: {node: '>=8'} - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - slice-ansi@8.0.0: - resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} - engines: {node: '>=20'} - smol-toml@1.7.0: resolution: {integrity: sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==} engines: {node: '>= 18'} @@ -3678,8 +3898,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@4.1.0: - resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} stdin-discarder@0.3.2: resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==} @@ -3701,6 +3921,10 @@ packages: resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} engines: {node: '>=20'} + string-width@8.2.2: + resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} + engines: {node: '>=20'} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -3744,8 +3968,8 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} engines: {node: '>=18'} tinyglobby@0.2.17: @@ -3756,10 +3980,14 @@ packages: resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} engines: {node: ^20.0.0 || >=22.0.0} - tinyrainbow@3.1.0: - resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + tinyrainbow@3.1.1: + resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -3773,18 +4001,18 @@ packages: peerDependencies: typescript: '>=4.8.4' - tsdown@0.22.3: - resolution: {integrity: sha512-louqbfA8Qf//B9jTTL0FPtXTNpjCWv1VPkbcmQMph2pTpzs+LnB1tbe4tDDRVpo2BjF5SgUXaTZe45SxB8pWHg==} + tsdown@0.22.14: + resolution: {integrity: sha512-ule7Y+fsAN2iZbLDoo7C4KYljFJNJJ+fLshyn+9gozeTspVersWHxwdGB+Dm2hzA38s6muFnUTl0jK3vJm9ifQ==} engines: {node: ^22.18.0 || >=24.11.0} hasBin: true peerDependencies: '@arethetypeswrong/core': ^0.18.1 - '@tsdown/css': 0.22.3 - '@tsdown/exe': 0.22.3 + '@tsdown/css': 0.22.14 + '@tsdown/exe': 0.22.14 '@vitejs/devtools': '*' publint: ^0.3.8 tsx: '*' - typescript: ^5.0.0 || ^6.0.0 + typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 unplugin-unused: ^0.5.0 unrun: '*' peerDependenciesMeta: @@ -3814,8 +4042,8 @@ packages: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - turbo@2.10.1: - resolution: {integrity: sha512-z9WGX2bAfElLOri8JY6pcwr+GfS18B5iGefLcvv3nwM9MoE/fPQQhpgZKTRlBciqGSDuLnfNyfP+eji8mEapQA==} + turbo@2.10.12: + resolution: {integrity: sha512-AswgMPnpOoaVZHrrSBejETzEbuIA69OVGwfkHwfrY0A23VjWXBANzgq9+OymWOHAIArB7D1+1z498WY8fGg1Jw==} hasBin: true type-check@0.4.0: @@ -3839,14 +4067,19 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@7.0.2: + resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} + engines: {node: '>=16.20.0'} + hasBin: true + unconfig-core@7.5.0: resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} - undici@6.27.0: - resolution: {integrity: sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==} + undici@6.28.0: + resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} engines: {node: '>=18.17'} unicode-emoji-modifier-base@1.0.0: @@ -3884,6 +4117,10 @@ packages: resolution: {integrity: sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==} engines: {node: '>= 0.10'} + verkit@0.3.2: + resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} + engines: {node: '>=18.12.0'} + vite@8.1.0: resolution: {integrity: sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3927,20 +4164,20 @@ packages: yaml: optional: true - vitest@4.1.9: - resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} + vitest@4.1.11: + resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.9 - '@vitest/browser-preview': 4.1.9 - '@vitest/browser-webdriverio': 4.1.9 - '@vitest/coverage-istanbul': 4.1.9 - '@vitest/coverage-v8': 4.1.9 - '@vitest/ui': 4.1.9 + '@vitest/browser-playwright': 4.1.11 + '@vitest/browser-preview': 4.1.11 + '@vitest/browser-webdriverio': 4.1.11 + '@vitest/coverage-istanbul': 4.1.11 + '@vitest/coverage-v8': 4.1.11 + '@vitest/ui': 4.1.11 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3995,14 +4232,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrap-ansi@10.0.0: - resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} - engines: {node: '>=20'} - - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -4049,22 +4278,27 @@ packages: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + yargs@18.1.0: + resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yoctocolors-cjs@2.1.3: - resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} - engines: {node: '>=18'} - yoctocolors@2.1.2: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} + yuku-ast@0.8.7: + resolution: {integrity: sha512-h6+4bDfyootiMB9vckk5uKo5r5j0GHrkr17FQTDNfEsFT3DWlN9uu1HJwQwc64pgmLCI945fWM3lbTIqxjT3GQ==} + + yuku-codegen@0.8.7: + resolution: {integrity: sha512-adwDZSh8oVDzhE6Du9PwVWxcOxeV0e2EVhUuMKWfhSY4wkrDq9eqixlxFF3l/XGUV1E7UFzhpz9393MUumkyNw==} + + yuku-parser@0.8.7: + resolution: {integrity: sha512-vRD9nwt4L3aYpxNqeSC4WqLv58xrXef0Ong1Mc45CTXTIpvLafx7JO05sczmQZwdLEZvywrLOGdNC5+Rp5N1BQ==} + snapshots: '@actions/core@3.0.1': @@ -4079,51 +4313,51 @@ snapshots: '@actions/github@9.1.1': dependencies: '@actions/http-client': 3.0.2 - '@octokit/core': 7.0.6 - '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - undici: 6.27.0 + '@octokit/core': 7.0.7 + '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.7) + '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.7) + '@octokit/request': 10.0.15 + '@octokit/request-error': 7.1.1 + undici: 6.28.0 '@actions/http-client@3.0.2': dependencies: tunnel: 0.0.6 - undici: 6.27.0 + undici: 6.28.0 '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 - undici: 6.27.0 + undici: 6.28.0 '@actions/io@3.0.2': {} - '@angular-devkit/core@21.2.17(chokidar@5.0.0)': + '@angular-devkit/core@22.1.6(chokidar@5.0.0)': dependencies: - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) jsonc-parser: 3.3.1 - picomatch: 4.0.4 + picomatch: 4.0.5 rxjs: 7.8.2 source-map: 0.7.6 optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/schematics-cli@21.2.17(@types/node@26.0.1)(chokidar@5.0.0)': + '@angular-devkit/schematics-cli@22.1.6(@types/node@26.4.0)(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) - '@inquirer/prompts': 7.10.1(@types/node@26.0.1) + '@angular-devkit/core': 22.1.6(chokidar@5.0.0) + '@angular-devkit/schematics': 22.1.6(chokidar@5.0.0) + '@inquirer/prompts': 8.5.2(@types/node@26.4.0) transitivePeerDependencies: - '@types/node' - chokidar - '@angular-devkit/schematics@21.2.17(chokidar@5.0.0)': + '@angular-devkit/schematics@22.1.6(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 22.1.6(chokidar@5.0.0) jsonc-parser: 3.3.1 - magic-string: 0.30.21 - ora: 9.3.0 + magic-string: 1.0.0 + ora: 9.4.1 rxjs: 7.8.2 transitivePeerDependencies: - chokidar @@ -4134,69 +4368,47 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/generator@7.29.7': - dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/generator@8.0.0': + '@babel/generator@7.29.8': dependencies: - '@babel/parser': 8.0.0 - '@babel/types': 8.0.0 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@types/jsesc': 2.5.1 jsesc: 3.1.0 '@babel/helper-globals@7.29.7': {} '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-string-parser@8.0.0': {} - '@babel/helper-validator-identifier@7.29.7': {} - '@babel/helper-validator-identifier@8.0.2': {} - - '@babel/parser@7.29.7': - dependencies: - '@babel/types': 7.29.7 - - '@babel/parser@8.0.0': + '@babel/parser@7.29.8': dependencies: - '@babel/types': 8.0.0 + '@babel/types': 7.29.8 '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 - '@babel/traverse@7.29.7': + '@babel/traverse@7.29.8(supports-color@10.2.2)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/types': 7.29.7 - debug: 4.4.3 + '@babel/types': 7.29.8 + debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color - '@babel/types@7.29.7': + '@babel/types@7.29.8': dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/types@8.0.0': - dependencies: - '@babel/helper-string-parser': 8.0.0 - '@babel/helper-validator-identifier': 8.0.2 - '@bcoe/v8-coverage@1.0.2': {} '@clack/core@0.5.0': @@ -4213,26 +4425,26 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commitlint/cli@21.2.0(@types/node@26.0.1)(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)(typescript@6.0.3)': + '@commitlint/cli@21.2.2(@types/node@26.4.0)(conventional-commits-parser@7.1.2)(typescript@7.0.2)': dependencies: - '@commitlint/config-conventional': 21.2.0 - '@commitlint/format': 21.2.0 - '@commitlint/lint': 21.2.0 - '@commitlint/load': 21.2.0(@types/node@26.0.1)(typescript@6.0.3) - '@commitlint/read': 21.2.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) + '@commitlint/config-conventional': 21.2.2 + '@commitlint/format': 21.2.2 + '@commitlint/lint': 21.2.2 + '@commitlint/load': 21.2.2(@types/node@26.4.0)(typescript@7.0.2) + '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.2) '@commitlint/types': 21.2.0 - tinyexec: 1.2.4 - yargs: 18.0.0 + tinyexec: 1.3.0 + yargs: 18.1.0 transitivePeerDependencies: - '@types/node' - conventional-commits-filter - conventional-commits-parser - typescript - '@commitlint/config-conventional@21.2.0': + '@commitlint/config-conventional@21.2.2': dependencies: '@commitlint/types': 21.2.0 - conventional-changelog-conventionalcommits: 10.2.0 + conventional-changelog-conventionalcommits: 10.4.0 '@commitlint/config-validator@21.2.0': dependencies: @@ -4242,36 +4454,36 @@ snapshots: '@commitlint/ensure@21.2.0': dependencies: '@commitlint/types': 21.2.0 - es-toolkit: 1.49.0 + es-toolkit: 1.51.0 '@commitlint/execute-rule@21.0.1': {} - '@commitlint/format@21.2.0': + '@commitlint/format@21.2.2': dependencies: '@commitlint/types': 21.2.0 picocolors: 1.1.1 - '@commitlint/is-ignored@21.2.0': + '@commitlint/is-ignored@21.2.2': dependencies: '@commitlint/types': 21.2.0 semver: 7.8.5 - '@commitlint/lint@21.2.0': + '@commitlint/lint@21.2.2': dependencies: - '@commitlint/is-ignored': 21.2.0 - '@commitlint/parse': 21.2.0 - '@commitlint/rules': 21.2.0 + '@commitlint/is-ignored': 21.2.2 + '@commitlint/parse': 21.2.2 + '@commitlint/rules': 21.2.2 '@commitlint/types': 21.2.0 - '@commitlint/load@21.2.0(@types/node@26.0.1)(typescript@6.0.3)': + '@commitlint/load@21.2.2(@types/node@26.4.0)(typescript@7.0.2)': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/execute-rule': 21.0.1 - '@commitlint/resolve-extends': 21.2.0 + '@commitlint/resolve-extends': 21.2.2 '@commitlint/types': 21.2.0 - cosmiconfig: 9.0.2(typescript@6.0.3) - cosmiconfig-typescript-loader: 6.3.0(@types/node@26.0.1)(cosmiconfig@9.0.2(typescript@6.0.3))(typescript@6.0.3) - es-toolkit: 1.49.0 + cosmiconfig: 9.0.2(typescript@7.0.2) + cosmiconfig-typescript-loader: 6.3.0(@types/node@26.4.0)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2) + es-toolkit: 1.51.0 is-plain-obj: 4.1.0 picocolors: 1.1.1 transitivePeerDependencies: @@ -4280,31 +4492,31 @@ snapshots: '@commitlint/message@21.2.0': {} - '@commitlint/parse@21.2.0': + '@commitlint/parse@21.2.2': dependencies: '@commitlint/types': 21.2.0 - conventional-changelog-angular: 9.2.0 - conventional-commits-parser: 7.0.0 + conventional-changelog-angular: 9.4.0 + conventional-commits-parser: 7.1.2 - '@commitlint/read@21.2.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': + '@commitlint/read@21.2.1(conventional-commits-parser@7.1.2)': dependencies: '@commitlint/top-level': 21.2.0 '@commitlint/types': 21.2.0 - git-raw-commits: 5.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) - tinyexec: 1.2.4 + '@conventional-changelog/git-client': 3.1.2(conventional-commits-parser@7.1.2) + tinyexec: 1.3.0 transitivePeerDependencies: - conventional-commits-filter - conventional-commits-parser - '@commitlint/resolve-extends@21.2.0': + '@commitlint/resolve-extends@21.2.2': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/types': 21.2.0 - es-toolkit: 1.49.0 + es-toolkit: 1.51.0 global-directory: 5.0.0 resolve-from: 5.0.0 - '@commitlint/rules@21.2.0': + '@commitlint/rules@21.2.2': dependencies: '@commitlint/ensure': 21.2.0 '@commitlint/message': 21.2.0 @@ -4319,7 +4531,7 @@ snapshots: '@commitlint/types@21.2.0': dependencies: - conventional-commits-parser: 7.0.0 + conventional-commits-parser: 7.1.2 picocolors: 1.1.1 '@conventional-changelog/git-client@2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': @@ -4331,7 +4543,15 @@ snapshots: conventional-commits-filter: 5.0.0 conventional-commits-parser: 6.4.0 - '@conventional-changelog/template@1.2.0': {} + '@conventional-changelog/git-client@3.1.2(conventional-commits-parser@7.1.2)': + dependencies: + '@simple-libs/child-process-utils': 2.0.0 + '@simple-libs/stream-utils': 2.0.0 + semver: 7.8.5 + optionalDependencies: + conventional-commits-parser: 7.1.2 + + '@conventional-changelog/template@1.4.0': {} '@dprint/formatter@0.5.1': {} @@ -4355,22 +4575,22 @@ snapshots: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.6.0(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.10.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))': dependencies: - eslint: 10.6.0(jiti@2.6.1) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.23.5': + '@eslint/config-array@0.23.5(supports-color@10.2.2)': dependencies: '@eslint/object-schema': 3.0.5 - debug: 4.4.3 - minimatch: 10.2.5 + debug: 4.4.3(supports-color@10.2.2) + minimatch: 10.2.6 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.6.0': + '@eslint/config-helpers@0.7.0': dependencies: '@eslint/core': 1.2.1 @@ -4378,9 +4598,9 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.6.0(jiti@2.6.1))': + '@eslint/js@10.0.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))': optionalDependencies: - eslint: 10.6.0(jiti@2.6.1) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) '@eslint/object-schema@3.0.5': {} @@ -4412,7 +4632,7 @@ snapshots: '@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/react-virtual': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-virtual': 3.14.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) client-only: 0.0.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -4433,249 +4653,124 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@inquirer/ansi@1.0.2': {} - '@inquirer/ansi@2.0.7': {} - '@inquirer/checkbox@4.3.2(@types/node@26.0.1)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.0.1) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/checkbox@5.2.1(@types/node@26.0.1)': + '@inquirer/checkbox@5.2.1(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/confirm@5.1.21(@types/node@26.0.1)': + '@inquirer/confirm@6.1.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/confirm@6.1.1(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/core@10.3.2(@types/node@26.0.1)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.0.1) - cli-width: 4.1.0 - mute-stream: 2.0.0 - signal-exit: 4.1.0 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/core@11.2.1(@types/node@26.0.1)': + '@inquirer/core@11.2.1(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/type': 4.0.7(@types/node@26.4.0) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/editor@4.2.23(@types/node@26.0.1)': + '@inquirer/editor@5.2.2(@types/node@26.4.0)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/external-editor': 1.0.3(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/external-editor': 3.0.3(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/editor@5.2.2(@types/node@26.0.1)': + '@inquirer/expand@5.1.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/external-editor': 3.0.3(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/expand@4.0.23(@types/node@26.0.1)': + '@inquirer/external-editor@3.0.3(@types/node@26.4.0)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) - yoctocolors-cjs: 2.1.3 + chardet: 2.2.0 + iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 + + '@inquirer/figures@2.0.7': {} - '@inquirer/expand@5.1.1(@types/node@26.0.1)': + '@inquirer/input@5.1.2(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/external-editor@1.0.3(@types/node@26.0.1)': + '@inquirer/number@4.1.1(@types/node@26.4.0)': dependencies: - chardet: 2.2.0 - iconv-lite: 0.7.2 + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/external-editor@3.0.3(@types/node@26.0.1)': - dependencies: - chardet: 2.2.0 - iconv-lite: 0.7.2 - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/figures@1.0.15': {} - - '@inquirer/figures@2.0.7': {} - - '@inquirer/input@4.3.1(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/input@5.1.2(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/number@3.0.23(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/number@4.1.1(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/password@4.0.23(@types/node@26.0.1)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/password@5.1.1(@types/node@26.0.1)': + '@inquirer/password@5.1.1(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/prompts@7.10.1(@types/node@26.0.1)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@26.0.1) - '@inquirer/confirm': 5.1.21(@types/node@26.0.1) - '@inquirer/editor': 4.2.23(@types/node@26.0.1) - '@inquirer/expand': 4.0.23(@types/node@26.0.1) - '@inquirer/input': 4.3.1(@types/node@26.0.1) - '@inquirer/number': 3.0.23(@types/node@26.0.1) - '@inquirer/password': 4.0.23(@types/node@26.0.1) - '@inquirer/rawlist': 4.1.11(@types/node@26.0.1) - '@inquirer/search': 3.2.2(@types/node@26.0.1) - '@inquirer/select': 4.4.2(@types/node@26.0.1) + '@types/node': 26.4.0 + + '@inquirer/prompts@8.5.2(@types/node@26.4.0)': + dependencies: + '@inquirer/checkbox': 5.2.1(@types/node@26.4.0) + '@inquirer/confirm': 6.1.1(@types/node@26.4.0) + '@inquirer/editor': 5.2.2(@types/node@26.4.0) + '@inquirer/expand': 5.1.1(@types/node@26.4.0) + '@inquirer/input': 5.1.2(@types/node@26.4.0) + '@inquirer/number': 4.1.1(@types/node@26.4.0) + '@inquirer/password': 5.1.1(@types/node@26.4.0) + '@inquirer/rawlist': 5.3.1(@types/node@26.4.0) + '@inquirer/search': 4.2.1(@types/node@26.4.0) + '@inquirer/select': 5.2.1(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/prompts@8.5.2(@types/node@26.0.1)': - dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@26.0.1) - '@inquirer/confirm': 6.1.1(@types/node@26.0.1) - '@inquirer/editor': 5.2.2(@types/node@26.0.1) - '@inquirer/expand': 5.1.1(@types/node@26.0.1) - '@inquirer/input': 5.1.2(@types/node@26.0.1) - '@inquirer/number': 4.1.1(@types/node@26.0.1) - '@inquirer/password': 5.1.1(@types/node@26.0.1) - '@inquirer/rawlist': 5.3.1(@types/node@26.0.1) - '@inquirer/search': 4.2.1(@types/node@26.0.1) - '@inquirer/select': 5.2.1(@types/node@26.0.1) - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/rawlist@4.1.11(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/type': 3.0.10(@types/node@26.0.1) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/rawlist@5.3.1(@types/node@26.0.1)': + '@inquirer/rawlist@5.3.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/search@3.2.2(@types/node@26.0.1)': + '@inquirer/search@4.2.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.0.1) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/search@4.2.1(@types/node@26.0.1)': - dependencies: - '@inquirer/core': 11.2.1(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/select@4.4.2(@types/node@26.0.1)': - dependencies: - '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@26.0.1) - '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@26.0.1) - yoctocolors-cjs: 2.1.3 - optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/select@5.2.1(@types/node@26.0.1)': + '@inquirer/select@5.2.1(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.0.1) + '@inquirer/core': 11.2.1(@types/node@26.4.0) '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.0.1) + '@inquirer/type': 4.0.7(@types/node@26.4.0) optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@inquirer/type@3.0.10(@types/node@26.0.1)': + '@inquirer/type@4.0.7(@types/node@26.4.0)': optionalDependencies: - '@types/node': 26.0.1 - - '@inquirer/type@4.0.7(@types/node@26.0.1)': - optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 '@isaacs/fs-minipass@4.0.1': dependencies: @@ -4695,11 +4790,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@mapbox/node-pre-gyp@2.0.3': + '@mapbox/node-pre-gyp@2.0.3(supports-color@10.2.2)': dependencies: consola: 3.4.2 detect-libc: 2.1.2 - https-proxy-agent: 7.0.6 + https-proxy-agent: 7.0.6(supports-color@10.2.2) node-fetch: 2.7.0 nopt: 8.1.0 semver: 7.8.5 @@ -4708,23 +4803,23 @@ snapshots: - encoding - supports-color - '@microsoft/api-extractor-model@7.33.8(@types/node@26.0.1)': + '@microsoft/api-extractor-model@7.33.11(@types/node@26.4.0)': dependencies: '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 - '@rushstack/node-core-library': 5.23.1(@types/node@26.0.1) + '@rushstack/node-core-library': 5.24.0(@types/node@26.4.0) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.58.9(@types/node@26.0.1)': + '@microsoft/api-extractor@7.59.0(@types/node@26.4.0)': dependencies: - '@microsoft/api-extractor-model': 7.33.8(@types/node@26.0.1) + '@microsoft/api-extractor-model': 7.33.11(@types/node@26.4.0) '@microsoft/tsdoc': 0.16.0 '@microsoft/tsdoc-config': 0.18.1 - '@rushstack/node-core-library': 5.23.1(@types/node@26.0.1) + '@rushstack/node-core-library': 5.24.0(@types/node@26.4.0) '@rushstack/rig-package': 0.7.3 - '@rushstack/terminal': 0.24.0(@types/node@26.0.1) - '@rushstack/ts-command-line': 5.3.10(@types/node@26.0.1) + '@rushstack/terminal': 0.24.3(@types/node@26.4.0) + '@rushstack/ts-command-line': 5.3.13(@types/node@26.4.0) diff: 8.0.4 minimatch: 10.2.3 resolve: 1.22.12 @@ -4760,14 +4855,14 @@ snapshots: commander: 15.0.0 semver: 7.8.5 - '@nanoforge-dev/cli@1.6.0(@types/node@26.0.1)': + '@nanoforge-dev/cli@1.6.2(@types/node@26.4.0)': dependencies: - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics-cli': 21.2.17(@types/node@26.0.1)(chokidar@5.0.0) - '@inquirer/prompts': 8.5.2(@types/node@26.0.1) - '@nanoforge-dev/loader-client': 1.3.0 - '@nanoforge-dev/loader-server': 1.2.0 - '@nanoforge-dev/schematics': 2.1.3(chokidar@5.0.0) + '@angular-devkit/schematics': 22.1.6(chokidar@5.0.0) + '@angular-devkit/schematics-cli': 22.1.6(@types/node@26.4.0)(chokidar@5.0.0) + '@inquirer/prompts': 8.5.2(@types/node@26.4.0) + '@nanoforge-dev/loader-client': 1.4.0 + '@nanoforge-dev/loader-server': 1.4.0 + '@nanoforge-dev/schematics': 2.2.1(chokidar@5.0.0) ansis: 4.3.1 bun: 1.3.14 chokidar: 5.0.0 @@ -4780,30 +4875,43 @@ snapshots: ora: 9.4.1 rc9: 3.0.1 reflect-metadata: 0.2.2 + optionalDependencies: + '@nanoforge-dev/editor': 0.1.4 transitivePeerDependencies: - '@types/node' - '@nanoforge-dev/loader-client@1.3.0': + '@nanoforge-dev/editor@0.1.4': dependencies: - '@nanoforge-dev/loader-website': 1.2.0 bun: 1.3.14 - commander: 14.0.3 + class-transformer: 0.5.1 + class-validator: 0.15.1 + dotenv: 17.4.2 + micromatch: 4.0.8 + tar: 7.5.19 + typescript: 6.0.3 + optional: true - '@nanoforge-dev/loader-server@1.2.0': + '@nanoforge-dev/loader-client@1.4.0': dependencies: - commander: 14.0.3 + '@nanoforge-dev/loader-website': 1.4.0 + bun: 1.3.14 + commander: 15.0.0 + + '@nanoforge-dev/loader-server@1.4.0': + dependencies: + commander: 15.0.0 - '@nanoforge-dev/loader-website@1.2.0': {} + '@nanoforge-dev/loader-website@1.4.0': {} - '@nanoforge-dev/schematics@2.1.3(chokidar@5.0.0)': + '@nanoforge-dev/schematics@2.2.1(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 22.1.6(chokidar@5.0.0) + '@angular-devkit/schematics': 22.1.6(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 @@ -4822,27 +4930,50 @@ snapshots: before-after-hook: 4.0.0 universal-user-agent: 7.0.3 + '@octokit/core@7.0.7': + dependencies: + '@octokit/auth-token': 6.0.0 + '@octokit/graphql': 9.0.4 + '@octokit/request': 10.0.15 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 + before-after-hook: 4.0.0 + universal-user-agent: 7.0.3 + '@octokit/endpoint@11.0.3': dependencies: '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 + '@octokit/endpoint@11.0.4': + dependencies: + '@octokit/types': 17.0.0 + universal-user-agent: 7.0.3 + '@octokit/graphql@9.0.3': dependencies: '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 + '@octokit/graphql@9.0.4': + dependencies: + '@octokit/request': 10.0.15 + '@octokit/types': 17.0.0 + universal-user-agent: 7.0.3 + '@octokit/openapi-types@27.0.0': {} - '@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.6)': + '@octokit/openapi-types@28.0.0': {} + + '@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.7)': dependencies: - '@octokit/core': 7.0.6 + '@octokit/core': 7.0.7 '@octokit/types': 16.0.0 - '@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.6)': + '@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.7)': dependencies: - '@octokit/core': 7.0.6 + '@octokit/core': 7.0.7 '@octokit/types': 16.0.0 '@octokit/plugin-retry@8.1.0(@octokit/core@7.0.6)': @@ -4856,6 +4987,10 @@ snapshots: dependencies: '@octokit/types': 16.0.0 + '@octokit/request-error@7.1.1': + dependencies: + '@octokit/types': 17.0.0 + '@octokit/request@10.0.10': dependencies: '@octokit/endpoint': 11.0.3 @@ -4865,19 +5000,23 @@ snapshots: json-with-bigint: 3.5.8 universal-user-agent: 7.0.3 - '@octokit/request@10.0.11': + '@octokit/request@10.0.15': dependencies: - '@octokit/endpoint': 11.0.3 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - content-type: 2.0.0 - json-with-bigint: 3.5.8 + '@octokit/endpoint': 11.0.4 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 + content-type: 3.0.0 + json-with-bigint: 3.5.12 universal-user-agent: 7.0.3 '@octokit/types@16.0.0': dependencies: '@octokit/openapi-types': 27.0.0 + '@octokit/types@17.0.0': + dependencies: + '@octokit/openapi-types': 28.0.0 + '@oven/bun-darwin-aarch64@1.3.14': optional: true @@ -4926,7 +5065,9 @@ snapshots: '@oven/bun-windows-x64@1.3.14': optional: true - '@oxc-project/types@0.137.0': {} + '@oxc-project/types@0.139.0': {} + + '@oxc-project/types@0.147.0': {} '@oxfmt/binding-android-arm-eabi@0.35.0': optional: true @@ -4991,58 +5132,103 @@ snapshots: dependencies: quansync: 1.0.0 - '@rolldown/binding-android-arm64@1.1.3': + '@rolldown/binding-android-arm-eabi@1.2.6': + optional: true + + '@rolldown/binding-android-arm64@1.1.5': + optional: true + + '@rolldown/binding-android-arm64@1.2.6': + optional: true + + '@rolldown/binding-darwin-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.6': + optional: true + + '@rolldown/binding-darwin-x64@1.1.5': + optional: true + + '@rolldown/binding-darwin-x64@1.2.6': + optional: true + + '@rolldown/binding-freebsd-x64@1.1.5': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.6': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.6': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.1.5': optional: true - '@rolldown/binding-darwin-arm64@1.1.3': + '@rolldown/binding-linux-arm64-gnu@1.2.6': optional: true - '@rolldown/binding-darwin-x64@1.1.3': + '@rolldown/binding-linux-arm64-musl@1.1.5': optional: true - '@rolldown/binding-freebsd-x64@1.1.3': + '@rolldown/binding-linux-arm64-musl@1.2.6': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.3': + '@rolldown/binding-linux-ppc64-gnu@1.1.5': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.3': + '@rolldown/binding-linux-ppc64-gnu@1.2.6': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.3': + '@rolldown/binding-linux-s390x-gnu@1.1.5': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.3': + '@rolldown/binding-linux-s390x-gnu@1.2.6': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.3': + '@rolldown/binding-linux-x64-gnu@1.1.5': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.3': + '@rolldown/binding-linux-x64-gnu@1.2.6': optional: true - '@rolldown/binding-linux-x64-musl@1.1.3': + '@rolldown/binding-linux-x64-musl@1.1.5': optional: true - '@rolldown/binding-openharmony-arm64@1.1.3': + '@rolldown/binding-linux-x64-musl@1.2.6': optional: true - '@rolldown/binding-wasm32-wasi@1.1.3': + '@rolldown/binding-openharmony-arm64@1.1.5': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.6': + optional: true + + '@rolldown/binding-wasm32-wasi@1.1.5': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.6': optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.3': + '@rolldown/binding-win32-x64-msvc@1.1.5': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.3': + '@rolldown/binding-win32-x64-msvc@1.2.6': optional: true '@rolldown/pluginutils@1.0.1': {} - '@rushstack/node-core-library@5.19.1(@types/node@26.0.1)': + '@rushstack/node-core-library@5.19.1(@types/node@26.4.0)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -5053,53 +5239,53 @@ snapshots: resolve: 1.22.12 semver: 7.5.4 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@rushstack/node-core-library@5.23.1(@types/node@26.0.1)': + '@rushstack/node-core-library@5.24.0(@types/node@26.4.0)': dependencies: - ajv: 8.18.0 - ajv-draft-04: 1.0.0(ajv@8.18.0) - ajv-formats: 3.0.1(ajv@8.18.0) + ajv: 8.20.0 + ajv-draft-04: 1.0.0(ajv@8.20.0) + ajv-formats: 3.0.1(ajv@8.20.0) fs-extra: 11.3.6 import-lazy: 4.0.0 jju: 1.4.0 resolve: 1.22.12 semver: 7.7.4 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@rushstack/problem-matcher@0.1.1(@types/node@26.0.1)': + '@rushstack/problem-matcher@0.1.1(@types/node@26.4.0)': optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@rushstack/problem-matcher@0.2.1(@types/node@26.0.1)': + '@rushstack/problem-matcher@0.2.1(@types/node@26.4.0)': optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 '@rushstack/rig-package@0.7.3': dependencies: jju: 1.4.0 resolve: 1.22.12 - '@rushstack/terminal@0.19.5(@types/node@26.0.1)': + '@rushstack/terminal@0.19.5(@types/node@26.4.0)': dependencies: - '@rushstack/node-core-library': 5.19.1(@types/node@26.0.1) - '@rushstack/problem-matcher': 0.1.1(@types/node@26.0.1) + '@rushstack/node-core-library': 5.19.1(@types/node@26.4.0) + '@rushstack/problem-matcher': 0.1.1(@types/node@26.4.0) supports-color: 8.1.1 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@rushstack/terminal@0.24.0(@types/node@26.0.1)': + '@rushstack/terminal@0.24.3(@types/node@26.4.0)': dependencies: - '@rushstack/node-core-library': 5.23.1(@types/node@26.0.1) - '@rushstack/problem-matcher': 0.2.1(@types/node@26.0.1) + '@rushstack/node-core-library': 5.24.0(@types/node@26.4.0) + '@rushstack/problem-matcher': 0.2.1(@types/node@26.4.0) supports-color: 8.1.1 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@rushstack/ts-command-line@5.3.10(@types/node@26.0.1)': + '@rushstack/ts-command-line@5.3.13(@types/node@26.4.0)': dependencies: - '@rushstack/terminal': 0.24.0(@types/node@26.0.1) + '@rushstack/terminal': 0.24.3(@types/node@26.4.0) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -5116,6 +5302,10 @@ snapshots: dependencies: '@simple-libs/stream-utils': 1.2.0 + '@simple-libs/child-process-utils@2.0.0': + dependencies: + '@simple-libs/stream-utils': 2.0.0 + '@simple-libs/stream-utils@1.2.0': {} '@simple-libs/stream-utils@2.0.0': {} @@ -5126,58 +5316,44 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@tanstack/react-virtual@3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@tanstack/react-virtual@3.14.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/virtual-core': 3.17.3 + '@tanstack/virtual-core': 3.17.8 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@tanstack/virtual-core@3.17.3': {} - - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.1)': - dependencies: - '@babel/generator': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 - javascript-natural-sort: 0.7.1 - lodash-es: 4.18.1 - minimatch: 9.0.9 - parse-imports-exports: 0.2.4 - prettier: 3.9.1 - transitivePeerDependencies: - - supports-color + '@tanstack/virtual-core@3.17.8': {} - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.4)': + '@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.6)(supports-color@10.2.2)': dependencies: - '@babel/generator': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.8 + '@babel/traverse': 7.29.8(supports-color@10.2.2) + '@babel/types': 7.29.8 javascript-natural-sort: 0.7.1 lodash-es: 4.18.1 minimatch: 9.0.9 parse-imports-exports: 0.2.4 - prettier: 3.9.4 + prettier: 3.9.6 transitivePeerDependencies: - supports-color - '@turbo/darwin-64@2.10.1': + '@turbo/darwin-64@2.10.12': optional: true - '@turbo/darwin-arm64@2.10.1': + '@turbo/darwin-arm64@2.10.12': optional: true - '@turbo/linux-64@2.10.1': + '@turbo/linux-64@2.10.12': optional: true - '@turbo/linux-arm64@2.10.1': + '@turbo/linux-arm64@2.10.12': optional: true - '@turbo/windows-64@2.10.1': + '@turbo/windows-64@2.10.12': optional: true - '@turbo/windows-arm64@2.10.1': + '@turbo/windows-arm64@2.10.12': optional: true '@tybys/wasm-util@0.10.3': @@ -5203,11 +5379,9 @@ snapshots: '@types/estree@1.0.9': {} - '@types/jsesc@2.5.1': {} - '@types/json-schema@7.0.15': {} - '@types/node@26.0.1': + '@types/node@26.4.0': dependencies: undici-types: 8.3.0 @@ -5215,42 +5389,42 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 - '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3))(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/parser': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/type-utils': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/type-utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) '@typescript-eslint/visitor-keys': 8.62.0 - eslint: 10.6.0(jiti@2.6.1) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 + ts-api-utils: 2.5.0(typescript@7.0.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': dependencies: '@typescript-eslint/scope-manager': 8.62.0 '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) '@typescript-eslint/visitor-keys': 8.62.0 - debug: 4.4.3 - eslint: 10.6.0(jiti@2.6.1) - typescript: 6.0.3 + debug: 4.4.3(supports-color@10.2.2) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.62.0(typescript@6.0.3)': + '@typescript-eslint/project-service@8.62.0(supports-color@10.2.2)(typescript@7.0.2)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@7.0.2) '@typescript-eslint/types': 8.62.0 - debug: 4.4.3 - typescript: 6.0.3 + debug: 4.4.3(supports-color@10.2.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color @@ -5259,47 +5433,47 @@ snapshots: '@typescript-eslint/types': 8.62.0 '@typescript-eslint/visitor-keys': 8.62.0 - '@typescript-eslint/tsconfig-utils@8.62.0(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.62.0(typescript@7.0.2)': dependencies: - typescript: 6.0.3 + typescript: 7.0.2 - '@typescript-eslint/type-utils@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': dependencies: '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) - debug: 4.4.3 - eslint: 10.6.0(jiti@2.6.1) - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 + '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + debug: 4.4.3(supports-color@10.2.2) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + ts-api-utils: 2.5.0(typescript@7.0.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color '@typescript-eslint/types@8.62.0': {} - '@typescript-eslint/typescript-estree@8.62.0(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.62.0(supports-color@10.2.2)(typescript@7.0.2)': dependencies: - '@typescript-eslint/project-service': 8.62.0(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@6.0.3) + '@typescript-eslint/project-service': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@7.0.2) '@typescript-eslint/types': 8.62.0 '@typescript-eslint/visitor-keys': 8.62.0 - debug: 4.4.3 - minimatch: 10.2.5 + debug: 4.4.3(supports-color@10.2.2) + minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 + ts-api-utils: 2.5.0(typescript@7.0.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/utils@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) '@typescript-eslint/scope-manager': 8.62.0 '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - eslint: 10.6.0(jiti@2.6.1) - typescript: 6.0.3 + '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color @@ -5308,68 +5482,202 @@ snapshots: '@typescript-eslint/types': 8.62.0 eslint-visitor-keys: 5.0.1 - '@vitest/coverage-v8@4.1.9(vitest@4.1.9)': + '@typescript/typescript-aix-ppc64@7.0.2': + optional: true + + '@typescript/typescript-darwin-arm64@7.0.2': + optional: true + + '@typescript/typescript-darwin-x64@7.0.2': + optional: true + + '@typescript/typescript-freebsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-freebsd-x64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm@7.0.2': + optional: true + + '@typescript/typescript-linux-loong64@7.0.2': + optional: true + + '@typescript/typescript-linux-mips64el@7.0.2': + optional: true + + '@typescript/typescript-linux-ppc64@7.0.2': + optional: true + + '@typescript/typescript-linux-riscv64@7.0.2': + optional: true + + '@typescript/typescript-linux-s390x@7.0.2': + optional: true + + '@typescript/typescript-linux-x64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-sunos-x64@7.0.2': + optional: true + + '@typescript/typescript-win32-arm64@7.0.2': + optional: true + + '@typescript/typescript-win32-x64@7.0.2': + optional: true + + '@vitest/coverage-v8@4.1.11(vitest@4.1.11)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.9 - ast-v8-to-istanbul: 1.0.4 + '@vitest/utils': 4.1.11 + ast-v8-to-istanbul: 1.0.5 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 - magicast: 0.5.3 - obug: 2.1.3 - std-env: 4.1.0 - tinyrainbow: 3.1.0 - vitest: 4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) + magicast: 0.5.4 + obug: 2.1.4 + std-env: 4.2.0 + tinyrainbow: 3.1.1 + vitest: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - '@vitest/expect@4.1.9': + '@vitest/expect@4.1.11': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 + '@vitest/spy': 4.1.11 + '@vitest/utils': 4.1.11 chai: 6.2.2 - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.9(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0))': + '@vitest/mocker@4.1.11(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.9 + '@vitest/spy': 4.1.11 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0) + vite: 8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0) - '@vitest/pretty-format@4.1.9': + '@vitest/pretty-format@4.1.11': dependencies: - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 - '@vitest/runner@4.1.9': + '@vitest/runner@4.1.11': dependencies: - '@vitest/utils': 4.1.9 + '@vitest/utils': 4.1.11 pathe: 2.0.3 - '@vitest/snapshot@4.1.9': + '@vitest/snapshot@4.1.11': dependencies: - '@vitest/pretty-format': 4.1.9 - '@vitest/utils': 4.1.9 + '@vitest/pretty-format': 4.1.11 + '@vitest/utils': 4.1.11 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.9': {} + '@vitest/spy@4.1.11': {} - '@vitest/utils@4.1.9': + '@vitest/utils@4.1.11': dependencies: - '@vitest/pretty-format': 4.1.9 + '@vitest/pretty-format': 4.1.11 convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 + tinyrainbow: 3.1.1 + + '@yuku-codegen/binding-android-arm64@0.8.7': + optional: true + + '@yuku-codegen/binding-darwin-arm64@0.8.7': + optional: true + + '@yuku-codegen/binding-darwin-x64@0.8.7': + optional: true + + '@yuku-codegen/binding-freebsd-x64@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm-gnu@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm-musl@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm64-gnu@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm64-musl@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-x64-gnu@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-x64-musl@0.8.7': + optional: true + + '@yuku-codegen/binding-win32-arm64@0.8.7': + optional: true + + '@yuku-codegen/binding-win32-x64@0.8.7': + optional: true + + '@yuku-parser/binding-android-arm64@0.8.7': + optional: true + + '@yuku-parser/binding-darwin-arm64@0.8.7': + optional: true + + '@yuku-parser/binding-darwin-x64@0.8.7': + optional: true + + '@yuku-parser/binding-freebsd-x64@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm-gnu@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm-musl@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm64-gnu@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm64-musl@0.8.7': + optional: true + + '@yuku-parser/binding-linux-x64-gnu@0.8.7': + optional: true + + '@yuku-parser/binding-linux-x64-musl@0.8.7': + optional: true + + '@yuku-parser/binding-win32-arm64@0.8.7': + optional: true + + '@yuku-parser/binding-win32-x64@0.8.7': + optional: true + + '@yuku-toolchain/types@0.8.7': {} abbrev@3.0.1: {} - acorn-jsx@5.3.2(acorn@8.17.0): + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: - acorn: 8.17.0 + acorn: 8.18.0 - acorn@8.17.0: {} + acorn@8.18.0: {} agent-base@7.1.4: {} @@ -5377,17 +5685,17 @@ snapshots: optionalDependencies: ajv: 8.13.0 - ajv-draft-04@1.0.0(ajv@8.18.0): + ajv-draft-04@1.0.0(ajv@8.20.0): optionalDependencies: - ajv: 8.18.0 + ajv: 8.20.0 ajv-formats@3.0.1(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 - ajv-formats@3.0.1(ajv@8.18.0): + ajv-formats@3.0.1(ajv@8.20.0): optionalDependencies: - ajv: 8.18.0 + ajv: 8.20.0 ajv@6.15.0: dependencies: @@ -5406,14 +5714,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.3 + fast-uri: 3.1.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.3 + fast-uri: 3.1.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -5425,10 +5733,6 @@ snapshots: ansi-regex@6.2.2: {} - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - ansi-styles@6.2.3: {} ansis@4.3.1: {} @@ -5439,6 +5743,8 @@ snapshots: argparse@2.0.1: {} + argue-cli@3.1.0: {} + assert@2.1.0: dependencies: call-bind: 1.0.9 @@ -5449,13 +5755,7 @@ snapshots: assertion-error@2.0.1: {} - ast-kit@3.0.0: - dependencies: - '@babel/parser': 8.0.0 - estree-walker: 3.0.3 - pathe: 2.0.3 - - ast-v8-to-istanbul@1.0.4: + ast-v8-to-istanbul@1.0.5: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -5473,18 +5773,21 @@ snapshots: before-after-hook@4.0.0: {} - birpc@4.0.0: {} - bottleneck@2.19.5: {} - brace-expansion@2.1.1: + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.7: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + optional: true + bun@1.3.14: optionalDependencies: '@oven/bun-darwin-aarch64': 1.3.14 @@ -5569,11 +5872,6 @@ snapshots: optionalDependencies: '@colors/colors': 1.5.0 - cli-truncate@5.2.0: - dependencies: - slice-ansi: 8.0.0 - string-width: 8.2.1 - cli-width@4.1.0: {} client-only@0.0.1: {} @@ -5588,12 +5886,6 @@ snapshots: clsx@2.1.1: {} - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - colorette@2.0.20: {} commander@10.0.1: {} @@ -5606,13 +5898,15 @@ snapshots: content-type@2.0.0: {} - conventional-changelog-angular@9.2.0: + content-type@3.0.0: {} + + conventional-changelog-angular@9.4.0: dependencies: - '@conventional-changelog/template': 1.2.0 + '@conventional-changelog/template': 1.4.0 - conventional-changelog-conventionalcommits@10.2.0: + conventional-changelog-conventionalcommits@10.4.0: dependencies: - '@conventional-changelog/template': 1.2.0 + '@conventional-changelog/template': 1.4.0 conventional-changelog-preset-loader@5.0.0: {} @@ -5623,10 +5917,10 @@ snapshots: '@simple-libs/stream-utils': 1.2.0 meow: 13.2.0 - conventional-commits-parser@7.0.0: + conventional-commits-parser@7.1.2: dependencies: '@simple-libs/stream-utils': 2.0.0 - meow: 14.1.0 + argue-cli: 3.1.0 conventional-recommended-bump@11.2.0: dependencies: @@ -5638,21 +5932,21 @@ snapshots: convert-source-map@2.0.0: {} - cosmiconfig-typescript-loader@6.3.0(@types/node@26.0.1)(cosmiconfig@9.0.2(typescript@6.0.3))(typescript@6.0.3): + cosmiconfig-typescript-loader@6.3.0(@types/node@26.4.0)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2): dependencies: - '@types/node': 26.0.1 - cosmiconfig: 9.0.2(typescript@6.0.3) + '@types/node': 26.4.0 + cosmiconfig: 9.0.2(typescript@7.0.2) jiti: 2.6.1 - typescript: 6.0.3 + typescript: 7.0.2 - cosmiconfig@9.0.2(typescript@6.0.3): + cosmiconfig@9.0.2(typescript@7.0.2): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 - js-yaml: 4.3.0 + js-yaml: 4.3.2 parse-json: 5.2.0 optionalDependencies: - typescript: 6.0.3 + typescript: 7.0.2 cross-spawn@7.0.6: dependencies: @@ -5660,9 +5954,11 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - debug@4.4.3: + debug@4.4.3(supports-color@10.2.2): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 10.2.2 deep-is@0.1.4: {} @@ -5734,21 +6030,21 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.2.0: {} + es-module-lexer@2.3.2: {} es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 - es-toolkit@1.49.0: {} + es-toolkit@1.51.0: {} escalade@3.2.0: {} escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.6.0(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)): dependencies: - eslint: 10.6.0(jiti@2.6.1) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) eslint-formatter-pretty@7.1.0: dependencies: @@ -5761,35 +6057,35 @@ snapshots: string-width: 8.2.1 supports-hyperlinks: 4.5.0 - eslint-formatting-reporter@0.0.0(eslint@10.6.0(jiti@2.6.1)): + eslint-formatting-reporter@0.0.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)): dependencies: - eslint: 10.6.0(jiti@2.6.1) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) prettier-linter-helpers: 1.0.1 eslint-parser-plain@0.1.1: {} - eslint-plugin-format@2.0.1(eslint@10.6.0(jiti@2.6.1)): + eslint-plugin-format@2.0.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)): dependencies: '@dprint/formatter': 0.5.1 '@dprint/markdown': 0.21.1 '@dprint/toml': 0.7.0 - eslint: 10.6.0(jiti@2.6.1) - eslint-formatting-reporter: 0.0.0(eslint@10.6.0(jiti@2.6.1)) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + eslint-formatting-reporter: 0.0.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) eslint-parser-plain: 0.1.1 ohash: 2.0.11 oxfmt: 0.35.0 - prettier: 3.9.1 + prettier: 3.9.6 synckit: 0.11.13 - eslint-plugin-prettier@5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.6.0(jiti@2.6.1)))(eslint@10.6.0(jiti@2.6.1))(prettier@3.9.1): + eslint-plugin-prettier@5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(prettier@3.9.6): dependencies: - eslint: 10.6.0(jiti@2.6.1) - prettier: 3.9.1 + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + prettier: 3.9.6 prettier-linter-helpers: 1.0.1 synckit: 0.11.13 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@10.6.0(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) eslint-rule-docs@1.1.235: {} @@ -5804,12 +6100,12 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.6.0(jiti@2.6.1): + eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.5 - '@eslint/config-helpers': 0.6.0 + '@eslint/config-array': 0.23.5(supports-color@10.2.2) + '@eslint/config-helpers': 0.7.0 '@eslint/core': 1.2.1 '@eslint/plugin-kit': 0.7.2 '@humanfs/node': 0.16.8 @@ -5818,7 +6114,7 @@ snapshots: '@types/estree': 1.0.9 ajv: 6.15.0 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) escape-string-regexp: 4.0.0 eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 @@ -5833,7 +6129,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.5 + minimatch: 10.2.6 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -5843,8 +6139,8 @@ snapshots: espree@11.2.0: dependencies: - acorn: 8.17.0 - acorn-jsx: 5.3.2(acorn@8.17.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 5.0.1 esquery@1.7.0: @@ -5863,8 +6159,6 @@ snapshots: esutils@2.0.3: {} - eventemitter3@5.0.4: {} - execa@9.6.1: dependencies: '@sindresorhus/merge-streams': 4.0.0 @@ -5896,15 +6190,15 @@ snapshots: dependencies: fast-string-truncated-width: 3.0.3 - fast-uri@3.1.3: {} + fast-uri@3.1.6: {} fast-wrap-ansi@0.2.2: dependencies: fast-string-width: 3.0.2 - fdir@6.5.0(picomatch@4.0.4): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.4 + picomatch: 4.0.7 figures@6.1.0: dependencies: @@ -5918,6 +6212,11 @@ snapshots: dependencies: minimatch: 5.1.9 + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + optional: true + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -5925,10 +6224,10 @@ snapshots: flat-cache@4.0.1: dependencies: - flatted: 3.4.2 + flatted: 3.4.4 keyv: 4.5.4 - flatted@3.4.2: {} + flatted@3.4.4: {} for-each@0.3.5: dependencies: @@ -6007,14 +6306,6 @@ snapshots: git-cliff-windows-arm64: 2.13.1 git-cliff-windows-x64: 2.13.1 - git-raw-commits@5.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0): - dependencies: - '@conventional-changelog/git-client': 2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) - meow: 13.2.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -6051,10 +6342,10 @@ snapshots: html-escaper@2.0.2: {} - https-proxy-agent@7.0.6: + https-proxy-agent@7.0.6(supports-color@10.2.2): dependencies: agent-base: 7.1.4 - debug: 4.4.3 + debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: - supports-color @@ -6108,10 +6399,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.6.0 - is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 @@ -6137,6 +6424,9 @@ snapshots: call-bind: 1.0.9 define-properties: 1.2.1 + is-number@7.0.0: + optional: true + is-plain-obj@4.1.0: {} is-regex@1.2.1: @@ -6193,6 +6483,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -6205,6 +6499,8 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json-with-bigint@3.5.12: {} + json-with-bigint@3.5.8: {} jsonc-parser@3.3.1: {} @@ -6228,78 +6524,69 @@ snapshots: libphonenumber-js@1.13.7: {} - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 lines-and-columns@1.2.4: {} - lint-staged@17.0.8: + lint-staged@17.3.0: dependencies: - listr2: 10.2.2 - picomatch: 4.0.4 + picomatch: 4.0.7 string-argv: 0.3.2 - tinyexec: 1.2.4 + tinyexec: 1.3.0 optionalDependencies: yaml: 2.9.0 - liquidjs@10.27.1: + liquidjs@10.29.0: dependencies: commander: 10.0.1 - listr2@10.2.2: - dependencies: - cli-truncate: 5.2.0 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 10.0.0 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -6313,14 +6600,6 @@ snapshots: is-unicode-supported: 2.1.0 yoctocolors: 2.1.2 - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -6333,10 +6612,14 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.5.3: + magic-string@1.0.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.4: dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 source-map-js: 1.2.1 make-dir@4.0.0: @@ -6347,25 +6630,29 @@ snapshots: meow@13.2.0: {} - meow@14.1.0: {} + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + optional: true mimic-function@5.0.1: {} minimatch@10.2.3: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 5.0.9 - minimatch@10.2.5: + minimatch@10.2.6: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 5.0.9 minimatch@5.1.9: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 2.1.4 minimatch@9.0.9: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 2.1.4 minipass@7.1.3: {} @@ -6373,30 +6660,30 @@ snapshots: dependencies: minipass: 7.1.3 - mint-tsdocs@0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.0.1)(@typescript-eslint/parser@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3))(eslint@10.6.0(jiti@2.6.1))(react-dom@18.3.1(react@18.3.1))(typescript@6.0.3): + mint-tsdocs@0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.4.0)(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(react-dom@18.3.1(react@18.3.1))(supports-color@10.2.2)(typescript@7.0.2): dependencies: '@clack/prompts': 0.11.0 - '@microsoft/api-extractor': 7.58.9(@types/node@26.0.1) - '@microsoft/api-extractor-model': 7.33.8(@types/node@26.0.1) + '@microsoft/api-extractor': 7.59.0(@types/node@26.4.0) + '@microsoft/api-extractor-model': 7.33.11(@types/node@26.4.0) '@microsoft/tsdoc': 0.16.0 '@mintlify/components': 0.3.15(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@rushstack/node-core-library': 5.23.1(@types/node@26.0.1) - '@rushstack/terminal': 0.19.5(@types/node@26.0.1) - '@rushstack/ts-command-line': 5.3.10(@types/node@26.0.1) + '@rushstack/node-core-library': 5.24.0(@types/node@26.4.0) + '@rushstack/terminal': 0.19.5(@types/node@26.4.0) + '@rushstack/ts-command-line': 5.3.13(@types/node@26.4.0) chalk: 5.6.2 cli-table3: 0.6.5 clsx: 2.1.1 - cosmiconfig: 9.0.2(typescript@6.0.3) - debug: 4.4.3 + cosmiconfig: 9.0.2(typescript@7.0.2) + debug: 4.4.3(supports-color@10.2.2) ejs: 3.1.10 is-unicode-supported: 2.1.0 - liquidjs: 10.27.1 - minimatch: 10.2.5 + liquidjs: 10.29.0 + minimatch: 10.2.6 react: 18.3.1 resolve: 1.22.12 optionalDependencies: - '@typescript-eslint/parser': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) - eslint: 10.6.0(jiti@2.6.1) + '@typescript-eslint/parser': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) transitivePeerDependencies: - '@headlessui/react' - '@types/node' @@ -6406,11 +6693,9 @@ snapshots: ms@2.1.3: {} - mute-stream@2.0.0: {} - mute-stream@3.0.0: {} - nanoid@3.3.15: {} + nanoid@3.3.18: {} natural-compare@1.4.0: {} @@ -6450,7 +6735,7 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 - obug@2.1.3: {} + obug@2.1.4: {} ohash@2.0.11: {} @@ -6476,17 +6761,6 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - ora@9.3.0: - dependencies: - chalk: 5.6.2 - cli-cursor: 5.0.0 - cli-spinners: 3.4.0 - is-interactive: 2.0.0 - is-unicode-supported: 2.1.0 - log-symbols: 7.0.1 - stdin-discarder: 0.3.2 - string-width: 8.2.1 - ora@9.4.1: dependencies: chalk: 5.6.2 @@ -6561,7 +6835,12 @@ snapshots: picocolors@1.1.1: {} - picomatch@4.0.4: {} + picomatch@2.3.2: + optional: true + + picomatch@4.0.5: {} + + picomatch@4.0.7: {} plur@5.1.0: dependencies: @@ -6569,9 +6848,9 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss@8.5.16: + postcss@8.5.26: dependencies: - nanoid: 3.3.15 + nanoid: 3.3.18 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -6583,9 +6862,7 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier@3.9.1: {} - - prettier@3.9.4: {} + prettier@3.9.6: {} pretty-ms@9.3.0: dependencies: @@ -6634,44 +6911,61 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 - rfdc@1.4.1: {} - - rolldown-plugin-dts@0.26.0(rolldown@1.1.3)(typescript@6.0.3): + rolldown-plugin-dts@0.27.14(rolldown@1.2.6)(typescript@7.0.2): dependencies: - '@babel/generator': 8.0.0 - '@babel/helper-validator-identifier': 8.0.2 - '@babel/parser': 8.0.0 - ast-kit: 3.0.0 - birpc: 4.0.0 dts-resolver: 3.0.0 get-tsconfig: 5.0.0-beta.5 - obug: 2.1.3 - rolldown: 1.1.3 + obug: 2.1.4 + rolldown: 1.2.6 + yuku-ast: 0.8.7 + yuku-codegen: 0.8.7 + yuku-parser: 0.8.7 optionalDependencies: - typescript: 6.0.3 + typescript: 7.0.2 transitivePeerDependencies: - oxc-resolver - rolldown@1.1.3: + rolldown@1.1.5: dependencies: - '@oxc-project/types': 0.137.0 + '@oxc-project/types': 0.139.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.3 - '@rolldown/binding-darwin-arm64': 1.1.3 - '@rolldown/binding-darwin-x64': 1.1.3 - '@rolldown/binding-freebsd-x64': 1.1.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.3 - '@rolldown/binding-linux-arm64-gnu': 1.1.3 - '@rolldown/binding-linux-arm64-musl': 1.1.3 - '@rolldown/binding-linux-ppc64-gnu': 1.1.3 - '@rolldown/binding-linux-s390x-gnu': 1.1.3 - '@rolldown/binding-linux-x64-gnu': 1.1.3 - '@rolldown/binding-linux-x64-musl': 1.1.3 - '@rolldown/binding-openharmony-arm64': 1.1.3 - '@rolldown/binding-wasm32-wasi': 1.1.3 - '@rolldown/binding-win32-arm64-msvc': 1.1.3 - '@rolldown/binding-win32-x64-msvc': 1.1.3 + '@rolldown/binding-android-arm64': 1.1.5 + '@rolldown/binding-darwin-arm64': 1.1.5 + '@rolldown/binding-darwin-x64': 1.1.5 + '@rolldown/binding-freebsd-x64': 1.1.5 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 + '@rolldown/binding-linux-arm64-gnu': 1.1.5 + '@rolldown/binding-linux-arm64-musl': 1.1.5 + '@rolldown/binding-linux-ppc64-gnu': 1.1.5 + '@rolldown/binding-linux-s390x-gnu': 1.1.5 + '@rolldown/binding-linux-x64-gnu': 1.1.5 + '@rolldown/binding-linux-x64-musl': 1.1.5 + '@rolldown/binding-openharmony-arm64': 1.1.5 + '@rolldown/binding-wasm32-wasi': 1.1.5 + '@rolldown/binding-win32-arm64-msvc': 1.1.5 + '@rolldown/binding-win32-x64-msvc': 1.1.5 + + rolldown@1.2.6: + dependencies: + '@oxc-project/types': 0.147.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm-eabi': 1.2.6 + '@rolldown/binding-android-arm64': 1.2.6 + '@rolldown/binding-darwin-arm64': 1.2.6 + '@rolldown/binding-darwin-x64': 1.2.6 + '@rolldown/binding-freebsd-x64': 1.2.6 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.6 + '@rolldown/binding-linux-arm64-gnu': 1.2.6 + '@rolldown/binding-linux-arm64-musl': 1.2.6 + '@rolldown/binding-linux-ppc64-gnu': 1.2.6 + '@rolldown/binding-linux-s390x-gnu': 1.2.6 + '@rolldown/binding-linux-x64-gnu': 1.2.6 + '@rolldown/binding-linux-x64-musl': 1.2.6 + '@rolldown/binding-openharmony-arm64': 1.2.6 + '@rolldown/binding-win32-arm64-msvc': 1.2.6 + '@rolldown/binding-win32-x64-msvc': 1.2.6 run-applescript@7.1.0: {} @@ -6724,16 +7018,6 @@ snapshots: dependencies: unicode-emoji-modifier-base: 1.0.0 - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - slice-ansi@8.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - smol-toml@1.7.0: {} source-map-js@1.2.1: {} @@ -6746,7 +7030,7 @@ snapshots: stackback@0.0.2: {} - std-env@4.1.0: {} + std-env@4.2.0: {} stdin-discarder@0.3.2: {} @@ -6769,6 +7053,11 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 + string-width@8.2.2: + dependencies: + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -6810,26 +7099,31 @@ snapshots: tinybench@2.9.0: {} - tinyexec@1.2.4: {} + tinyexec@1.3.0: {} tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 tinypool@2.1.0: {} - tinyrainbow@3.1.0: {} + tinyrainbow@3.1.1: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + optional: true tr46@0.0.3: {} tree-kill@1.2.2: {} - ts-api-utils@2.5.0(typescript@6.0.3): + ts-api-utils@2.5.0(typescript@7.0.2): dependencies: - typescript: 6.0.3 + typescript: 7.0.2 - tsdown@0.22.3(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)): + tsdown@0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)): dependencies: ansis: 4.3.1 cac: 7.0.0 @@ -6837,21 +7131,21 @@ snapshots: empathic: 2.0.1 hookable: 6.1.1 import-without-cache: 0.4.0 - obug: 2.1.3 - picomatch: 4.0.4 - rolldown: 1.1.3 - rolldown-plugin-dts: 0.26.0(rolldown@1.1.3)(typescript@6.0.3) - semver: 7.8.5 - tinyexec: 1.2.4 + obug: 2.1.4 + picomatch: 4.0.7 + rolldown: 1.2.6 + rolldown-plugin-dts: 0.27.14(rolldown@1.2.6)(typescript@7.0.2) + tinyexec: 1.3.0 tinyglobby: 0.2.17 tree-kill: 1.2.2 unconfig-core: 7.5.0 + verkit: 0.3.2 optionalDependencies: - typescript: 6.0.3 + typescript: 7.0.2 unrun: 0.3.1(synckit@0.11.13) transitivePeerDependencies: - - '@ts-macro/tsc' - '@typescript/native-preview' + - '@volar/typescript' - oxc-resolver - vue-tsc @@ -6859,33 +7153,57 @@ snapshots: tunnel@0.0.6: {} - turbo@2.10.1: + turbo@2.10.12: optionalDependencies: - '@turbo/darwin-64': 2.10.1 - '@turbo/darwin-arm64': 2.10.1 - '@turbo/linux-64': 2.10.1 - '@turbo/linux-arm64': 2.10.1 - '@turbo/windows-64': 2.10.1 - '@turbo/windows-arm64': 2.10.1 + '@turbo/darwin-64': 2.10.12 + '@turbo/darwin-arm64': 2.10.12 + '@turbo/linux-64': 2.10.12 + '@turbo/linux-arm64': 2.10.12 + '@turbo/windows-64': 2.10.12 + '@turbo/windows-arm64': 2.10.12 type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3): + typescript-eslint@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3))(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/parser': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) - '@typescript-eslint/utils': 8.62.0(eslint@10.6.0(jiti@2.6.1))(typescript@6.0.3) - eslint: 10.6.0(jiti@2.6.1) - typescript: 6.0.3 + '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/parser': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + typescript: 7.0.2 transitivePeerDependencies: - supports-color typescript@5.9.3: {} - typescript@6.0.3: {} + typescript@6.0.3: + optional: true + + typescript@7.0.2: + optionalDependencies: + '@typescript/typescript-aix-ppc64': 7.0.2 + '@typescript/typescript-darwin-arm64': 7.0.2 + '@typescript/typescript-darwin-x64': 7.0.2 + '@typescript/typescript-freebsd-arm64': 7.0.2 + '@typescript/typescript-freebsd-x64': 7.0.2 + '@typescript/typescript-linux-arm': 7.0.2 + '@typescript/typescript-linux-arm64': 7.0.2 + '@typescript/typescript-linux-loong64': 7.0.2 + '@typescript/typescript-linux-mips64el': 7.0.2 + '@typescript/typescript-linux-ppc64': 7.0.2 + '@typescript/typescript-linux-riscv64': 7.0.2 + '@typescript/typescript-linux-s390x': 7.0.2 + '@typescript/typescript-linux-x64': 7.0.2 + '@typescript/typescript-netbsd-arm64': 7.0.2 + '@typescript/typescript-netbsd-x64': 7.0.2 + '@typescript/typescript-openbsd-arm64': 7.0.2 + '@typescript/typescript-openbsd-x64': 7.0.2 + '@typescript/typescript-sunos-x64': 7.0.2 + '@typescript/typescript-win32-arm64': 7.0.2 + '@typescript/typescript-win32-x64': 7.0.2 unconfig-core@7.5.0: dependencies: @@ -6894,7 +7212,7 @@ snapshots: undici-types@8.3.0: {} - undici@6.27.0: {} + undici@6.28.0: {} unicode-emoji-modifier-base@1.0.0: {} @@ -6906,7 +7224,7 @@ snapshots: unrun@0.3.1(synckit@0.11.13): dependencies: - rolldown: 1.1.3 + rolldown: 1.2.6 optionalDependencies: synckit: 0.11.13 @@ -6924,44 +7242,46 @@ snapshots: validator@13.15.35: {} - vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0): + verkit@0.3.2: {} + + vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.16 - rolldown: 1.1.3 + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.26 + rolldown: 1.1.5 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 26.0.1 + '@types/node': 26.4.0 fsevents: 2.3.3 jiti: 2.6.1 yaml: 2.9.0 - vitest@4.1.9(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)): + vitest@4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.9 - '@vitest/mocker': 4.1.9(vite@8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.9 - '@vitest/runner': 4.1.9 - '@vitest/snapshot': 4.1.9 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 - es-module-lexer: 2.2.0 + '@vitest/expect': 4.1.11 + '@vitest/mocker': 4.1.11(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.11 + '@vitest/runner': 4.1.11 + '@vitest/snapshot': 4.1.11 + '@vitest/spy': 4.1.11 + '@vitest/utils': 4.1.11 + es-module-lexer: 2.3.2 expect-type: 1.4.0 magic-string: 0.30.21 - obug: 2.1.3 + obug: 2.1.4 pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.1.0 + picomatch: 4.0.7 + std-env: 4.2.0 tinybench: 2.9.0 - tinyexec: 1.2.4 + tinyexec: 1.3.0 tinyglobby: 0.2.17 - tinyrainbow: 3.1.0 - vite: 8.1.0(@types/node@26.0.1)(jiti@2.6.1)(yaml@2.9.0) + tinyrainbow: 3.1.1 + vite: 8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 26.0.1 - '@vitest/coverage-v8': 4.1.9(vitest@4.1.9) + '@types/node': 26.4.0 + '@vitest/coverage-v8': 4.1.11(vitest@4.1.11) transitivePeerDependencies: - msw @@ -6996,18 +7316,6 @@ snapshots: word-wrap@1.2.5: {} - wrap-ansi@10.0.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 8.2.1 - strip-ansi: 7.2.0 - - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -7036,17 +7344,54 @@ snapshots: yargs-parser@22.0.0: {} - yargs@18.0.0: + yargs@18.1.0: dependencies: cliui: 9.0.1 escalade: 3.2.0 get-caller-file: 2.0.5 - string-width: 7.2.0 + string-width: 8.2.2 y18n: 5.0.8 yargs-parser: 22.0.0 yocto-queue@0.1.0: {} - yoctocolors-cjs@2.1.3: {} - yoctocolors@2.1.2: {} + + yuku-ast@0.8.7: + dependencies: + '@yuku-toolchain/types': 0.8.7 + + yuku-codegen@0.8.7: + dependencies: + '@yuku-toolchain/types': 0.8.7 + optionalDependencies: + '@yuku-codegen/binding-android-arm64': 0.8.7 + '@yuku-codegen/binding-darwin-arm64': 0.8.7 + '@yuku-codegen/binding-darwin-x64': 0.8.7 + '@yuku-codegen/binding-freebsd-x64': 0.8.7 + '@yuku-codegen/binding-linux-arm-gnu': 0.8.7 + '@yuku-codegen/binding-linux-arm-musl': 0.8.7 + '@yuku-codegen/binding-linux-arm64-gnu': 0.8.7 + '@yuku-codegen/binding-linux-arm64-musl': 0.8.7 + '@yuku-codegen/binding-linux-x64-gnu': 0.8.7 + '@yuku-codegen/binding-linux-x64-musl': 0.8.7 + '@yuku-codegen/binding-win32-arm64': 0.8.7 + '@yuku-codegen/binding-win32-x64': 0.8.7 + + yuku-parser@0.8.7: + dependencies: + '@yuku-toolchain/types': 0.8.7 + yuku-ast: 0.8.7 + optionalDependencies: + '@yuku-parser/binding-android-arm64': 0.8.7 + '@yuku-parser/binding-darwin-arm64': 0.8.7 + '@yuku-parser/binding-darwin-x64': 0.8.7 + '@yuku-parser/binding-freebsd-x64': 0.8.7 + '@yuku-parser/binding-linux-arm-gnu': 0.8.7 + '@yuku-parser/binding-linux-arm-musl': 0.8.7 + '@yuku-parser/binding-linux-arm64-gnu': 0.8.7 + '@yuku-parser/binding-linux-arm64-musl': 0.8.7 + '@yuku-parser/binding-linux-x64-gnu': 0.8.7 + '@yuku-parser/binding-linux-x64-musl': 0.8.7 + '@yuku-parser/binding-win32-arm64': 0.8.7 + '@yuku-parser/binding-win32-x64': 0.8.7 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 90ba3659..bfa59cce 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -10,24 +10,24 @@ allowBuilds: catalogs: build: - tsdown: ^0.22.3 + tsdown: ^0.22.14 unrun: ^0.3.0 ci: - '@commitlint/cli': ^21.2.0 - '@commitlint/config-conventional': ^21.2.0 + '@commitlint/cli': ^21.2.2 + '@commitlint/config-conventional': ^21.2.2 '@favware/cliff-jumper': ^6.0.0 '@nanoforge-dev/actions': ^2.1.5 husky: ^9.1.7 - lint-staged: ^17.0.8 + lint-staged: ^17.3.0 config: class-transformer: ^0.5.1 class-validator: ^0.14.3 core: - '@types/node': ^26.0.1 - turbo: ^2.10.1 - typescript: ^6.0.3 + '@types/node': ^26.4.0 + turbo: ^2.10.12 + typescript: ^7.0.2 docs: - '@microsoft/api-extractor': ^7.58.9 + '@microsoft/api-extractor': ^7.59.0 mint-tsdocs: ^0.0.8 typedoc: ^0.28.19 typedoc-plugin-markdown: ^4.11.0 @@ -36,13 +36,13 @@ catalogs: lint: '@eslint/js': ^10.0.1 '@trivago/prettier-plugin-sort-imports': ^6.0.2 - eslint: ^10.6.0 + eslint: ^10.9.1 eslint-config-prettier: ^10.1.8 eslint-formatter-pretty: ^7.1.0 eslint-plugin-format: ^2.0.1 eslint-plugin-prettier: ^5.5.5 globals: ^17.3.0 - prettier: ^3.9.4 + prettier: ^3.9.6 typescript-eslint: ^8.61.0 network: '@mapbox/node-pre-gyp': ^2.0.3 @@ -50,5 +50,5 @@ catalogs: wrtc: ^0.4.7 ws: ^8.20.1 test: - '@vitest/coverage-v8': ^4.1.9 - vitest: ^4.1.9 + '@vitest/coverage-v8': ^4.1.11 + vitest: ^4.1.11 diff --git a/utils/eslint-config/package.json b/utils/eslint-config/package.json index 25790056..e9e050ce 100644 --- a/utils/eslint-config/package.json +++ b/utils/eslint-config/package.json @@ -58,9 +58,9 @@ "eslint": "catalog:lint", "prettier": "catalog:lint" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" diff --git a/utils/prettier-config/package.json b/utils/prettier-config/package.json index e05118a0..dd835c29 100644 --- a/utils/prettier-config/package.json +++ b/utils/prettier-config/package.json @@ -47,9 +47,9 @@ "@trivago/prettier-plugin-sort-imports": "catalog:lint", "prettier": "catalog:lint" }, - "packageManager": "pnpm@11.5.2", + "packageManager": "pnpm@11.24.0", "engines": { - "node": "25" + "node": "26" }, "publishConfig": { "access": "public" From 2116d56dd72fa1cae05b5112727c4243fb1e2ab1 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sat, 29 Aug 2026 15:02:15 +0200 Subject: [PATCH 02/12] feat: add new pong network (#414) --- example/pong-network/.gitignore | 229 ------------------ example/pong-network/README.md | 1 - .../pong-network/apps/client/assets/.gitkeep | 0 .../apps/client/nanoforge.config.ts | 7 + example/pong-network/apps/client/package.json | 39 +++ .../client/src/components}/components.ts | 2 +- .../{client => apps/client/src}/main.ts | 42 ++-- .../apps/client/src/scenes/.gitkeep | 0 .../client/src/systems}/systems.ts | 10 +- .../pong-network/apps/server/assets/.gitkeep | 0 .../apps/server/nanoforge.config.ts | 5 + example/pong-network/apps/server/package.json | 37 +++ .../server/src/components}/components.ts | 0 .../{server => apps/server/src}/main.ts | 28 +-- .../apps/server/src/scenes/.gitkeep | 0 .../server/src/systems}/systems.ts | 6 +- example/pong-network/eslint.config.js | 3 - example/pong-network/index.d.ts | 65 +++++ .../libs/test-lib/nanoforge.config.ts | 5 + example/pong-network/nanoforge.config.json | 21 -- example/pong-network/nanoforge.config.ts | 6 + example/pong-network/package.json | 19 +- example/pong-network/prettier.config.js | 3 - example/pong-network/tsconfig.json | 42 +--- 24 files changed, 213 insertions(+), 357 deletions(-) delete mode 100644 example/pong-network/README.md create mode 100644 example/pong-network/apps/client/assets/.gitkeep create mode 100644 example/pong-network/apps/client/nanoforge.config.ts create mode 100644 example/pong-network/apps/client/package.json rename example/pong-network/{client => apps/client/src/components}/components.ts (97%) rename example/pong-network/{client => apps/client/src}/main.ts (75%) create mode 100644 example/pong-network/apps/client/src/scenes/.gitkeep rename example/pong-network/{client => apps/client/src/systems}/systems.ts (90%) create mode 100644 example/pong-network/apps/server/assets/.gitkeep create mode 100644 example/pong-network/apps/server/nanoforge.config.ts create mode 100644 example/pong-network/apps/server/package.json rename example/pong-network/{server => apps/server/src/components}/components.ts (100%) rename example/pong-network/{server => apps/server/src}/main.ts (53%) create mode 100644 example/pong-network/apps/server/src/scenes/.gitkeep rename example/pong-network/{server => apps/server/src/systems}/systems.ts (96%) delete mode 100644 example/pong-network/eslint.config.js create mode 100644 example/pong-network/index.d.ts create mode 100644 example/pong-network/libs/test-lib/nanoforge.config.ts delete mode 100644 example/pong-network/nanoforge.config.json create mode 100644 example/pong-network/nanoforge.config.ts delete mode 100644 example/pong-network/prettier.config.js diff --git a/example/pong-network/.gitignore b/example/pong-network/.gitignore index ba254b9c..e69de29b 100644 --- a/example/pong-network/.gitignore +++ b/example/pong-network/.gitignore @@ -1,229 +0,0 @@ -### 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.* - -### Private - -# Nanoforge -.nanoforge/ diff --git a/example/pong-network/README.md b/example/pong-network/README.md deleted file mode 100644 index 776d79c3..00000000 --- a/example/pong-network/README.md +++ /dev/null @@ -1 +0,0 @@ -# pong-network diff --git a/example/pong-network/apps/client/assets/.gitkeep b/example/pong-network/apps/client/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/example/pong-network/apps/client/nanoforge.config.ts b/example/pong-network/apps/client/nanoforge.config.ts new file mode 100644 index 00000000..ab6e23e1 --- /dev/null +++ b/example/pong-network/apps/client/nanoforge.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "client", + + libs: ["../../libs/test-lib"], // ? or ["test-lib"] (with a name set in config or in pkg.json) or ["libs/test-lib"] +}); diff --git a/example/pong-network/apps/client/package.json b/example/pong-network/apps/client/package.json new file mode 100644 index 00000000..246b97c8 --- /dev/null +++ b/example/pong-network/apps/client/package.json @@ -0,0 +1,39 @@ +{ + "name": "pong-network-client", + "version": "0.0.0", + "description": "", + "author": "", + "scripts": { + "build": "nf build", + "start": "nf start", + "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"", + "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"" + }, + "devDependencies": { + "@nanoforge-dev/asset": "workspace:*", + "@nanoforge-dev/common": "workspace:*", + "@nanoforge-dev/config": "workspace:*", + "@nanoforge-dev/core": "workspace:*", + "@nanoforge-dev/env": "workspace:*", + "@nanoforge-dev/ecs-client": "workspace:*", + "@nanoforge-dev/network-client": "workspace:*", + "@nanoforge-dev/graphics-2d": "workspace:*", + "@nanoforge-dev/input": "workspace:*", + "@nanoforge-dev/utils-eslint-config": "workspace:*", + "@nanoforge-dev/utils-prettier-config": "workspace:*", + "@trivago/prettier-plugin-sort-imports": "catalog:lint", + "eslint": "catalog:lint", + "lint-staged": "catalog:ci", + "prettier": "catalog:lint", + "typescript": "catalog:core" + }, + "private": true, + "lint-staged": { + "**": [ + "prettier --ignore-unknown --write" + ], + "{client,server}/**/*.ts": [ + "eslint --fix" + ] + } +} diff --git a/example/pong-network/client/components.ts b/example/pong-network/apps/client/src/components/components.ts similarity index 97% rename from example/pong-network/client/components.ts rename to example/pong-network/apps/client/src/components/components.ts index f71b6536..616891b0 100644 --- a/example/pong-network/client/components.ts +++ b/example/pong-network/apps/client/src/components/components.ts @@ -1,7 +1,7 @@ import type { Circle, Rect } from "@nanoforge-dev/graphics-2d"; import type { InputEnum } from "@nanoforge-dev/input"; -import { layer } from "./main"; +import { layer } from "../main"; export class NetworkId { name = "NetworkId"; diff --git a/example/pong-network/client/main.ts b/example/pong-network/apps/client/src/main.ts similarity index 75% rename from example/pong-network/client/main.ts rename to example/pong-network/apps/client/src/main.ts index 0eb0a81e..4f1df8b2 100644 --- a/example/pong-network/client/main.ts +++ b/example/pong-network/apps/client/src/main.ts @@ -1,37 +1,36 @@ -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { type IRunOptions } from "@nanoforge-dev/common"; +import type { ClientRunOptions } from "@nanoforge-dev/common"; import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSClientLibrary } from "@nanoforge-dev/ecs-client"; +import { EcsLibrary } from "@nanoforge-dev/ecs-client"; import { Circle, Graphics2DLibrary, Layer, Rect } from "@nanoforge-dev/graphics-2d"; -import { InputEnum } from "@nanoforge-dev/input"; -import { InputLibrary } from "@nanoforge-dev/input"; +import { InputEnum, InputLibrary } from "@nanoforge-dev/input"; import { NetworkClientLibrary } from "@nanoforge-dev/network-client"; -import { CircleComponent, Controller, Position, RectangleComponent, Velocity } from "./components"; -import { controlPlayer, draw, move, packetHandler } from "./systems"; - -export const app = NanoforgeFactory.createClient({ - tickRate: 60, -}); +import { + CircleComponent, + Controller, + Position, + RectangleComponent, + Velocity, +} from "./components/components"; +import { controlPlayer, draw, move, packetHandler } from "./systems/systems"; export const layer = new Layer(); -export const main = async (options: IRunOptions) => { +export const main = async (options: ClientRunOptions): Promise => { + const app = NanoforgeFactory.createClient({ tickRate: 60 }); const graphics = new Graphics2DLibrary(); - const ecsLibrary = new ECSClientLibrary(); + const ecs = new EcsLibrary(); const network = new NetworkClientLibrary(); - const assetManager = new AssetManagerLibrary(); const input = new InputLibrary(); - app.useGraphics(graphics); - app.useComponentSystem(ecsLibrary); - app.useNetwork(network); - app.useAssetManager(assetManager); - app.useInput(input); + app.use(graphics); + app.use(ecs); + app.use(network); + app.use(input); await app.init(options); - const registry = ecsLibrary.registry; + const registry = ecs.registry; graphics.stage.add(layer); @@ -102,5 +101,6 @@ export const main = async (options: IRunOptions) => { await waitForConnection(); network.tcp.sendData(new TextEncoder().encode(JSON.stringify({ type: "play" }))); - app.run(); + + await app.run(); }; diff --git a/example/pong-network/apps/client/src/scenes/.gitkeep b/example/pong-network/apps/client/src/scenes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/example/pong-network/client/systems.ts b/example/pong-network/apps/client/src/systems/systems.ts similarity index 90% rename from example/pong-network/client/systems.ts rename to example/pong-network/apps/client/src/systems/systems.ts index 37d5dc18..f183f350 100644 --- a/example/pong-network/client/systems.ts +++ b/example/pong-network/apps/client/src/systems/systems.ts @@ -1,7 +1,5 @@ import { type Context } from "@nanoforge-dev/common"; import { type Registry } from "@nanoforge-dev/ecs-client"; -import { type InputLibrary } from "@nanoforge-dev/input"; -import { type NetworkClientLibrary } from "@nanoforge-dev/network-client"; import { CircleComponent, @@ -10,7 +8,7 @@ import { Position, RectangleComponent, Velocity, -} from "./components"; +} from "../components/components"; export function move(registry: Registry, ctx: Context) { const entities = registry.getZipper([Position, Velocity]); @@ -23,8 +21,8 @@ export function move(registry: Registry, ctx: Context) { export const controlPlayer = (registry: Registry, ctx: Context) => { const entities = registry.getZipper([Controller]); - const input = ctx.libs.getInput(); - const network = ctx.libs.getNetwork(); + const input = ctx.input; + const network = ctx.network; entities.forEach(({ Controller }) => { const upPressed = input.isKeyPressed(Controller.up); @@ -62,7 +60,7 @@ export function draw(registry: Registry) { } export function packetHandler(registry: Registry, ctx: Context) { - const network = ctx.libs.getNetwork(); + const network = ctx.network; const jsonPackets = network.tcp.getReceivedPackets().map((packet) => { return JSON.parse(new TextDecoder().decode(packet)); }); diff --git a/example/pong-network/apps/server/assets/.gitkeep b/example/pong-network/apps/server/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/example/pong-network/apps/server/nanoforge.config.ts b/example/pong-network/apps/server/nanoforge.config.ts new file mode 100644 index 00000000..bc5491cb --- /dev/null +++ b/example/pong-network/apps/server/nanoforge.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "server", +}); diff --git a/example/pong-network/apps/server/package.json b/example/pong-network/apps/server/package.json new file mode 100644 index 00000000..710ef94f --- /dev/null +++ b/example/pong-network/apps/server/package.json @@ -0,0 +1,37 @@ +{ + "name": "pong-network-server", + "version": "0.0.0", + "description": "", + "author": "", + "scripts": { + "build": "nf build", + "start": "nf start", + "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"", + "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"" + }, + "devDependencies": { + "@nanoforge-dev/asset": "workspace:*", + "@nanoforge-dev/common": "workspace:*", + "@nanoforge-dev/config": "workspace:*", + "@nanoforge-dev/core": "workspace:*", + "@nanoforge-dev/env": "workspace:*", + "@nanoforge-dev/ecs-server": "workspace:*", + "@nanoforge-dev/network-server": "workspace:*", + "@nanoforge-dev/utils-eslint-config": "workspace:*", + "@nanoforge-dev/utils-prettier-config": "workspace:*", + "@trivago/prettier-plugin-sort-imports": "catalog:lint", + "eslint": "catalog:lint", + "lint-staged": "catalog:ci", + "prettier": "catalog:lint", + "typescript": "catalog:core" + }, + "private": true, + "lint-staged": { + "**": [ + "prettier --ignore-unknown --write" + ], + "{client,server}/**/*.ts": [ + "eslint --fix" + ] + } +} diff --git a/example/pong-network/server/components.ts b/example/pong-network/apps/server/src/components/components.ts similarity index 100% rename from example/pong-network/server/components.ts rename to example/pong-network/apps/server/src/components/components.ts diff --git a/example/pong-network/server/main.ts b/example/pong-network/apps/server/src/main.ts similarity index 53% rename from example/pong-network/server/main.ts rename to example/pong-network/apps/server/src/main.ts index c30b6475..435454bb 100644 --- a/example/pong-network/server/main.ts +++ b/example/pong-network/apps/server/src/main.ts @@ -1,28 +1,22 @@ -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { type IRunOptions } from "@nanoforge-dev/common"; +import type { RunOptions } from "@nanoforge-dev/common"; import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSServerLibrary } from "@nanoforge-dev/ecs-server"; +import { EcsLibrary } from "@nanoforge-dev/ecs-server"; import { NetworkServerLibrary } from "@nanoforge-dev/network-server"; -import { Position, Velocity } from "./components"; -import { bounce, move, packetHandler } from "./systems"; +import { Position, Velocity } from "./components/components"; +import { bounce, move, packetHandler } from "./systems/systems"; -export const app = NanoforgeFactory.createServer({ - tickRate: 60, -}); - -export const main = async (options: IRunOptions) => { - const ecsLibrary = new ECSServerLibrary(); +export const main = async (options: RunOptions): Promise => { + const app = NanoforgeFactory.createServer({ tickRate: 60 }); + const ecs = new EcsLibrary(); const network = new NetworkServerLibrary(); - const assetManager = new AssetManagerLibrary(); - app.useComponentSystem(ecsLibrary); - app.useNetwork(network); - app.useAssetManager(assetManager); + app.use(ecs); + app.use(network); await app.init(options); - const registry = ecsLibrary.registry; + const registry = ecs.registry; const ball = registry.spawnEntity(); registry.addComponent(ball, new Position(960, 540)); @@ -40,5 +34,5 @@ export const main = async (options: IRunOptions) => { registry.addSystem(bounce); registry.addSystem(move); - app.run(); + await app.run(); }; diff --git a/example/pong-network/apps/server/src/scenes/.gitkeep b/example/pong-network/apps/server/src/scenes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/example/pong-network/server/systems.ts b/example/pong-network/apps/server/src/systems/systems.ts similarity index 96% rename from example/pong-network/server/systems.ts rename to example/pong-network/apps/server/src/systems/systems.ts index 68ac92a0..a16d75c3 100644 --- a/example/pong-network/server/systems.ts +++ b/example/pong-network/apps/server/src/systems/systems.ts @@ -2,7 +2,7 @@ import { type Context } from "@nanoforge-dev/common"; import { type Registry } from "@nanoforge-dev/ecs-server"; import { type NetworkServerLibrary } from "@nanoforge-dev/network-server"; -import { Position, Velocity } from "./components"; +import { Position, Velocity } from "../components/components"; let cli1 = -1; let cli2 = -1; @@ -84,7 +84,7 @@ function handleClientInput(clientId: number, key: string, network: NetworkServer export function packetHandler(registry: Registry, ctx: Context) { const zip = registry.getZipper([Position, Velocity]); - const network = ctx.libs.getNetwork(); + const network = ctx.network; if (network.tcp.getConnectedClients().indexOf(cli1) == -1) cli1 = -1; if (network.tcp.getConnectedClients().indexOf(cli2) == -1) cli2 = -1; @@ -124,7 +124,7 @@ function checkOutOfTerrain(id: number, paddle: any, network: NetworkServerLibrar } export const bounce = (registry: Registry, ctx: Context) => { - const network = ctx.libs.getNetwork(); + const network = ctx.network; const zip = registry.getZipper([Position, Velocity]); checkOutOfTerrain(1, zip[1], network); checkOutOfTerrain(2, zip[2], network); diff --git a/example/pong-network/eslint.config.js b/example/pong-network/eslint.config.js deleted file mode 100644 index 62ec06dc..00000000 --- a/example/pong-network/eslint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-eslint-config"; - -export default config; diff --git a/example/pong-network/index.d.ts b/example/pong-network/index.d.ts new file mode 100644 index 00000000..ea737668 --- /dev/null +++ b/example/pong-network/index.d.ts @@ -0,0 +1,65 @@ +// Ambient stub for the `nf` CLI's own `nanoforge/config` resolution. Keep this +// shape in sync with @nanoforge-dev/config's real types; revisit/remove once +// the CLI's actual resolution contract for `nanoforge.config.ts` is confirmed. +declare module "nanoforge/config" { + type ContainLibConfig = { + libs?: string[]; + }; + + type BuildableConfig = { + entryFile?: string; + out?: { + dir?: string; + mainFile?: string; + }; + }; + + type SourceableConfig = { + dir?: { + assets?: string; + + packages?: string; + + // Used by the editor only + components?: string; + + // Used by the editor only + systems?: string; + + // Used by the editor only + scenes?: string; + }; + }; + + type BaseConfig = { + type: Type; + }; + + type WorkspaceConfig = BaseConfig<"workspace"> & { + packages?: string[]; + }; + type LibConfig = BaseConfig<"lib"> & { + dir?: { + assets?: string; + shared?: string; + + // Used by the editor only + // Should be inside shared dir + components?: string; + + // Used by the editor only + // Should be inside shared dir + systems?: string; + + // Used by the editor only + // Should be inside shared dir + scenes?: string; + }; + }; + type ClientConfig = BaseConfig<"client"> & SourceableConfig & BuildableConfig & ContainLibConfig; + type ServerConfig = BaseConfig<"server"> & SourceableConfig & BuildableConfig & ContainLibConfig; + + export type Config = WorkspaceConfig | LibConfig | ClientConfig | ServerConfig; + + export const defineConfig: (config: Config) => any; +} diff --git a/example/pong-network/libs/test-lib/nanoforge.config.ts b/example/pong-network/libs/test-lib/nanoforge.config.ts new file mode 100644 index 00000000..cc139b25 --- /dev/null +++ b/example/pong-network/libs/test-lib/nanoforge.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "lib", +}); diff --git a/example/pong-network/nanoforge.config.json b/example/pong-network/nanoforge.config.json deleted file mode 100644 index 1e4becd5..00000000 --- a/example/pong-network/nanoforge.config.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "client": { - "build": { - "entryFile": "client/main.ts", - "outDir": ".nanoforge/client" - }, - "runtime": { - "dir": ".nanoforge/client" - } - }, - "server": { - "enable": true, - "build": { - "entryFile": "server/main.ts", - "outDir": ".nanoforge/server" - }, - "runtime": { - "dir": ".nanoforge/server" - } - } -} diff --git a/example/pong-network/nanoforge.config.ts b/example/pong-network/nanoforge.config.ts new file mode 100644 index 00000000..cc75b72c --- /dev/null +++ b/example/pong-network/nanoforge.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "workspace", + packages: ["apps/*", "libs/*"], +}); diff --git a/example/pong-network/package.json b/example/pong-network/package.json index 10e9981a..ab03589b 100644 --- a/example/pong-network/package.json +++ b/example/pong-network/package.json @@ -7,29 +7,22 @@ "build": "mkdir -p .nanoforge && nf build", "start": "nf start", "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"", - "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"" + "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"", + "test:unit": "vitest run --config ../../vitest.config.ts" }, "devDependencies": { - "@nanoforge-dev/asset-manager": "workspace:*", + "@nanoforge-dev/asset": "workspace:*", "@nanoforge-dev/cli": "latest", "@nanoforge-dev/common": "workspace:*", "@nanoforge-dev/config": "workspace:*", "@nanoforge-dev/core": "workspace:*", - "@nanoforge-dev/ecs-client": "workspace:*", - "@nanoforge-dev/ecs-server": "workspace:*", - "@nanoforge-dev/graphics-2d": "workspace:*", - "@nanoforge-dev/input": "workspace:*", - "@nanoforge-dev/network-client": "workspace:*", - "@nanoforge-dev/network-server": "workspace:*", - "@nanoforge-dev/music": "workspace:*", - "@nanoforge-dev/sound": "workspace:*", - "@nanoforge-dev/utils-eslint-config": "workspace:*", - "@nanoforge-dev/utils-prettier-config": "workspace:*", + "@nanoforge-dev/env": "workspace:*", "@trivago/prettier-plugin-sort-imports": "catalog:lint", "eslint": "catalog:lint", "lint-staged": "catalog:ci", "prettier": "catalog:lint", - "typescript": "catalog:core" + "typescript": "catalog:core", + "vitest": "catalog:test" }, "private": true, "lint-staged": { diff --git a/example/pong-network/prettier.config.js b/example/pong-network/prettier.config.js deleted file mode 100644 index 27d0e269..00000000 --- a/example/pong-network/prettier.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-prettier-config"; - -export default config; diff --git a/example/pong-network/tsconfig.json b/example/pong-network/tsconfig.json index 2e28238a..076ca025 100644 --- a/example/pong-network/tsconfig.json +++ b/example/pong-network/tsconfig.json @@ -1,42 +1,6 @@ { "$schema": "https://json.schemastore.org/tsconfig.json", - // Mapped from https://www.typescriptlang.org/tsconfig - "compilerOptions": { - // Type Checking - "allowUnreachableCode": false, - "allowUnusedLabels": false, - "exactOptionalPropertyTypes": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noImplicitReturns": true, - "noPropertyAccessFromIndexSignature": false, - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "strict": true, - - // Modules - "allowArbitraryExtensions": false, - "allowImportingTsExtensions": false, - "module": "ESNext", - "moduleResolution": "Bundler", - "resolveJsonModule": true, - "resolvePackageJsonExports": true, - "resolvePackageJsonImports": true, - - // Interop Constraints - "allowSyntheticDefaultImports": true, - "esModuleInterop": false, - "forceConsistentCasingInFileNames": true, - "isolatedModules": true, - - // Language and Environment - "rootDir": ".", - "lib": ["ESNext", "esnext.disposable", "DOM"], - "target": "ESNext", - "experimentalDecorators": true, - "useDefineForClassFields": true - }, - "include": ["client/**/*.ts", "server/**/*.ts"], - "exclude": ["node_modules", ".nanoforge"] + "extends": "../../tsconfig.json", + "include": ["apps/*/src/**/*.ts", "test/**/*.ts"], + "exclude": ["node_modules", "**/dist", "**/.nanoforge"] } From a0cd8673d4a3eb7293d29e6d5acab0088cfba1fa Mon Sep 17 00:00:00 2001 From: Exelo Date: Sat, 29 Aug 2026 22:17:55 +0200 Subject: [PATCH 03/12] feat: add new network (#419) --- .../network}/.cliff-jumperrc.json | 4 +- .../network}/.gitignore | 37 +------ .../input => modules/network}/.prettierignore | 0 modules/network/CHANGELOG.md | 3 + modules/network/LICENSE | 21 ++++ modules/network/README.md | 100 ++++++++++++++++++ modules/network/api-extractor.json | 39 +++++++ .../ecs-server => modules/network}/cliff.toml | 0 .../network}/eslint.config.js | 0 modules/network/mint-tsdocs.config.json | 19 ++++ .../network}/package.json | 43 +++++--- .../network}/prettier.config.js | 0 .../src/client/client.network.library.ts | 74 +++++++++++++ .../src/client}/config.client.network.ts | 6 +- .../src/client/context-augmentation.ts | 7 ++ .../network/src/client}/index.ts | 4 + .../src/client/network-client-context.type.ts | 10 ++ .../network/src/client}/tcp.client.network.ts | 0 .../network/src/client}/udp.client.network.ts | 0 .../network/src/client}/utils.ts | 0 .../src/server}/config.server.network.ts | 6 +- .../src/server/context-augmentation.ts | 7 ++ .../network/src/server}/index.ts | 4 + .../src/server/network-server-context.type.ts | 10 ++ .../src/server}/server.network.library.ts | 68 ++++++------ .../network/src/server}/tcp.server.network.ts | 0 .../network/src/server}/udp.server.network.ts | 0 .../network/src/server}/utils.ts | 0 modules/network/src/server/wrtc.d.ts | 1 + .../client}/client.network.library.spec.ts | 51 ++++++--- .../network/test/client}/tcp.client.spec.ts | 2 +- .../network/test/client}/udp.client.spec.ts | 2 +- .../network/test/client}/utils.spec.ts | 2 +- .../server}/server.network.library.spec.ts | 62 ++++++----- .../network/test/server}/tcp.server.spec.ts | 2 +- .../network/test/server}/udp.server.spec.ts | 2 +- .../network/test/server}/utils.spec.ts | 6 +- modules/network/tsconfig.client.json | 8 ++ .../network}/tsconfig.json | 0 modules/network/tsconfig.server.json | 8 ++ .../network}/tsconfig.spec.json | 0 .../ecs-server => modules/network}/tsdoc.json | 0 modules/network/tsdown.config.ts | 14 +++ 43 files changed, 472 insertions(+), 150 deletions(-) rename {packages/ecs-lib => modules/network}/.cliff-jumperrc.json (77%) rename {packages/graphics-2d-editor => modules/network}/.gitignore (93%) rename {packages/input => modules/network}/.prettierignore (100%) create mode 100644 modules/network/CHANGELOG.md create mode 100644 modules/network/LICENSE create mode 100644 modules/network/README.md create mode 100644 modules/network/api-extractor.json rename {packages/ecs-server => modules/network}/cliff.toml (100%) rename {packages/graphics-2d => modules/network}/eslint.config.js (100%) create mode 100644 modules/network/mint-tsdocs.config.json rename {packages/network-server => modules/network}/package.json (66%) rename {packages/graphics-2d-editor => modules/network}/prettier.config.js (100%) create mode 100644 modules/network/src/client/client.network.library.ts rename {packages/network-client/src => modules/network/src/client}/config.client.network.ts (83%) create mode 100644 modules/network/src/client/context-augmentation.ts rename {packages/network-client/src => modules/network/src/client}/index.ts (50%) create mode 100644 modules/network/src/client/network-client-context.type.ts rename {packages/network-client/src => modules/network/src/client}/tcp.client.network.ts (100%) rename {packages/network-client/src => modules/network/src/client}/udp.client.network.ts (100%) rename {packages/network-client/src => modules/network/src/client}/utils.ts (100%) rename {packages/network-server/src => modules/network/src/server}/config.server.network.ts (86%) create mode 100644 modules/network/src/server/context-augmentation.ts rename {packages/network-server/src => modules/network/src/server}/index.ts (50%) create mode 100644 modules/network/src/server/network-server-context.type.ts rename {packages/network-server/src => modules/network/src/server}/server.network.library.ts (50%) rename {packages/network-server/src => modules/network/src/server}/tcp.server.network.ts (100%) rename {packages/network-server/src => modules/network/src/server}/udp.server.network.ts (100%) rename {packages/network-server/src => modules/network/src/server}/utils.ts (100%) create mode 100644 modules/network/src/server/wrtc.d.ts rename {packages/network-client/test => modules/network/test/client}/client.network.library.spec.ts (63%) rename {packages/network-client/test => modules/network/test/client}/tcp.client.spec.ts (97%) rename {packages/network-client/test => modules/network/test/client}/udp.client.spec.ts (96%) rename {packages/network-client/test => modules/network/test/client}/utils.spec.ts (97%) rename {packages/network-server/test => modules/network/test/server}/server.network.library.spec.ts (52%) rename {packages/network-server/test => modules/network/test/server}/tcp.server.spec.ts (98%) rename {packages/network-server/test => modules/network/test/server}/udp.server.spec.ts (97%) rename {packages/network-server/test => modules/network/test/server}/utils.spec.ts (97%) create mode 100644 modules/network/tsconfig.client.json rename {packages/graphics-2d-editor => modules/network}/tsconfig.json (100%) create mode 100644 modules/network/tsconfig.server.json rename {packages/graphics-2d-editor => modules/network}/tsconfig.spec.json (100%) rename {packages/ecs-server => modules/network}/tsdoc.json (100%) create mode 100644 modules/network/tsdown.config.ts diff --git a/packages/ecs-lib/.cliff-jumperrc.json b/modules/network/.cliff-jumperrc.json similarity index 77% rename from packages/ecs-lib/.cliff-jumperrc.json rename to modules/network/.cliff-jumperrc.json index 7a76cd75..ebd62e89 100644 --- a/packages/ecs-lib/.cliff-jumperrc.json +++ b/modules/network/.cliff-jumperrc.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "ecs-lib", + "name": "network", "org": "nanoforge-dev", - "packagePath": "packages/ecs-lib", + "packagePath": "modules/network", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/graphics-2d-editor/.gitignore b/modules/network/.gitignore similarity index 93% rename from packages/graphics-2d-editor/.gitignore rename to modules/network/.gitignore index e56e932b..fee0a7b7 100644 --- a/packages/graphics-2d-editor/.gitignore +++ b/modules/network/.gitignore @@ -12,40 +12,6 @@ # 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 @@ -257,14 +223,13 @@ dist .yarn/install-state.gz .pnp.* -### Private - # Turbo .turbo/ # Compiled files src/**/*.js src/**/*.d.ts +!src/server/wrtc.d.ts # mint-tsdocs cache docs/.tsdocs/ diff --git a/packages/input/.prettierignore b/modules/network/.prettierignore similarity index 100% rename from packages/input/.prettierignore rename to modules/network/.prettierignore diff --git a/modules/network/CHANGELOG.md b/modules/network/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/network/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/modules/network/LICENSE b/modules/network/LICENSE new file mode 100644 index 00000000..46724861 --- /dev/null +++ b/modules/network/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright © 2026 NanoForge + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/network/README.md b/modules/network/README.md new file mode 100644 index 00000000..a4658513 --- /dev/null +++ b/modules/network/README.md @@ -0,0 +1,100 @@ +
+
+

+ NanoForge +

+
+

+ npm version + npm downloads + Tests status + Last commit + Contributors +

+
+ +## About + +`@nanoforge-dev/network` is NanoForge's built-in networking library. It ships two subpath entry points — `@nanoforge-dev/network/client` and `@nanoforge-dev/network/server` — each providing reliable, ordered TCP (WebSocket) and unreliable, unordered UDP (WebRTC data channel) transports. Splitting client and server into separate entry points keeps Node-only dependencies (`ws`, `wrtc`) out of a client's bundle graph entirely. + +## Installation + +**Node.js 26 or newer is required.** + +```sh +npm install @nanoforge-dev/network +yarn add @nanoforge-dev/network +pnpm add @nanoforge-dev/network +bun add @nanoforge-dev/network +``` + +## Warning + +Configuration is read from the environment via `@nanoforge-dev/env`. Put the relevant variables in your `.env` file (or `InitContext.env`): + +```dotenv +# Client +SERVER_ADDRESS=127.0.0.1 +SERVER_TCP_PORT=4445 +SERVER_UDP_PORT=4444 + +# Server +LISTENING_INTERFACE=0.0.0.0 +LISTENING_TCP_PORT=4445 +LISTENING_UDP_PORT=4444 +``` + +Either the TCP port or the UDP port (or both) must be set on each side. + +## Example usage + +```ts +// Client app +import { NetworkClientLibrary } from "@nanoforge-dev/network/client"; + +app.use(new NetworkClientLibrary()); + +public override async __run(ctx: Context): Promise { + ctx.network.tcp?.sendData(payload); + for (const packet of ctx.network.tcp?.getReceivedPackets() ?? []) { + // Handle incoming packets. + } +} +``` + +```ts +// Server app +import { NetworkServerLibrary } from "@nanoforge-dev/network/server"; + +app.use(new NetworkServerLibrary()); + +public override async __run(ctx: Context): Promise { + for (const clientId of ctx.network.tcp?.getConnectedClients() ?? []) { + ctx.network.tcp?.sendToClient(clientId, payload); + } + ctx.network.tcp?.sendToEverybody(broadcastPayload); +} +``` + +`ctx.network.tcp`/`.udp` are `undefined` when the corresponding port wasn't configured on that side. + +## Links + +- [GitHub][source] +- [npm][npm] + +## Contributing + +Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the +[documentation][documentation]. +See [the contribution guide][contributing] if you'd like to submit a PR. + +## Help + +If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. + +[documentation]: https://github.com/NanoForge-dev/Engine +[discussions]: https://github.com/NanoForge-dev/Engine/discussions +[source]: https://github.com/NanoForge-dev/Engine/tree/main/modules/network +[npm]: https://www.npmjs.com/package/@nanoforge-dev/network +[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/modules/network/api-extractor.json b/modules/network/api-extractor.json new file mode 100644 index 00000000..c24e7134 --- /dev/null +++ b/modules/network/api-extractor.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "projectFolder": ".", + "mainEntryPointFilePath": "/dist/client/index.d.ts", + "bundledPackages": [], + "compiler": { + "tsconfigFilePath": "/tsconfig.client.json" + }, + "apiReport": { + "enabled": false + }, + "docModel": { + "enabled": true, + "apiJsonFilePath": "/docs/.tsdocs/.api.json" + }, + "dtsRollup": { + "enabled": false + }, + "tsdocMetadata": { + "enabled": true + }, + "messages": { + "compilerMessageReporting": { + "default": { + "logLevel": "none" + } + }, + "extractorMessageReporting": { + "default": { + "logLevel": "none" + } + }, + "tsdocMessageReporting": { + "default": { + "logLevel": "none" + } + } + } +} diff --git a/packages/ecs-server/cliff.toml b/modules/network/cliff.toml similarity index 100% rename from packages/ecs-server/cliff.toml rename to modules/network/cliff.toml diff --git a/packages/graphics-2d/eslint.config.js b/modules/network/eslint.config.js similarity index 100% rename from packages/graphics-2d/eslint.config.js rename to modules/network/eslint.config.js diff --git a/modules/network/mint-tsdocs.config.json b/modules/network/mint-tsdocs.config.json new file mode 100644 index 00000000..e80bbb97 --- /dev/null +++ b/modules/network/mint-tsdocs.config.json @@ -0,0 +1,19 @@ +{ + "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", + "entryPoint": "dist/client/index.d.ts", + "outputFolder": "../../docs/references/network", + "apiExtractor": { + "configPath": "./api-extractor.json", + "compiler": { + "tsconfigFilePath": "tsconfig.client.json" + } + }, + "lint": { + "eslint": { + "enabled": true + } + }, + "templates": { + "userTemplateDir": "../../docs/templates" + } +} diff --git a/packages/network-server/package.json b/modules/network/package.json similarity index 66% rename from packages/network-server/package.json rename to modules/network/package.json index 92357362..4035b491 100644 --- a/packages/network-server/package.json +++ b/modules/network/package.json @@ -1,8 +1,8 @@ { "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/network-server", + "name": "@nanoforge-dev/network", "version": "1.4.2", - "description": "NanoForge Engine - Network Server", + "description": "NanoForge Engine - Network", "keywords": [ "nanoforge", "game", @@ -13,25 +13,36 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ "dist" ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", + "main": "./dist/client/index.cjs", + "module": "./dist/client/index.js", + "types": "./dist/client/index.d.cts", "exports": { - ".": { + "./client": { "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" + "types": "./dist/client/index.d.cts", + "default": "./dist/client/index.cjs" }, "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./dist/client/index.d.ts", + "default": "./dist/client/index.js" + } + }, + "./server": { + "require": { + "types": "./dist/server/index.d.cts", + "default": "./dist/server/index.cjs" + }, + "import": { + "types": "./dist/server/index.d.ts", + "default": "./dist/server/index.js" } }, "./package.json": "./package.json" @@ -43,23 +54,23 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/network-server" + "directory": "modules/network" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { - "build": "tsc --noEmit && tsdown --config-loader unrun", + "build": "tsc -p tsconfig.client.json --noEmit && tsc -p tsconfig.server.json --noEmit && tsdown --config-loader unrun", "lint": "prettier --check . && eslint --format=pretty src", "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/network-server/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/network/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, "dependencies": { "@mapbox/node-pre-gyp": "catalog:network", "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/config": "workspace:*", + "@nanoforge-dev/env": "workspace:*", "wrtc": "catalog:network", "ws": "catalog:network" }, @@ -76,7 +87,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/graphics-2d-editor/prettier.config.js b/modules/network/prettier.config.js similarity index 100% rename from packages/graphics-2d-editor/prettier.config.js rename to modules/network/prettier.config.js diff --git a/modules/network/src/client/client.network.library.ts b/modules/network/src/client/client.network.library.ts new file mode 100644 index 00000000..19867381 --- /dev/null +++ b/modules/network/src/client/client.network.library.ts @@ -0,0 +1,74 @@ +import { type InitContext, Library, defineLibraryKey } from "@nanoforge-dev/common"; +import { registerEnv } from "@nanoforge-dev/env"; + +import { ClientConfigNetwork } from "./config.client.network"; +import type { NetworkClientContextApi } from "./network-client-context.type"; +import { TCPClient } from "./tcp.client.network"; +import { UDPClient } from "./udp.client.network"; + +/** + * Built-in network library for client-side applications. + * + * @remarks + * Reads network configuration from the environment via `ClientConfigNetwork` + * and automatically connects to the server over TCP (WebSocket), UDP + * (WebRTC data channel), or both. + * + * Configuration (via environment variables): + * - `SERVER_ADDRESS` — hostname or IP of the server (required). + * - `SERVER_TCP_PORT` — WebSocket port for TCP (optional). + * - `SERVER_UDP_PORT` — signaling port for UDP/WebRTC (optional). + * - `MAGIC_VALUE` — packet framing delimiter (default: `"PACKET_END"`). + * - `WSS` — set to `"true"` to use `wss://` / `https://` (default: `false`). + */ +export class NetworkClientLibrary extends Library { + readonly key = defineLibraryKey("network"); + + /** Only set when `SERVER_TCP_PORT` was configured. */ + public tcp?: TCPClient; + /** Only set when `SERVER_UDP_PORT` was configured. */ + public udp?: UDPClient; + + public override async __init(ctx: InitContext): Promise { + const config = await registerEnv(ClientConfigNetwork, ctx.env); + + if (config.SERVER_TCP_PORT === undefined && config.SERVER_UDP_PORT === undefined) { + throw new Error("NetworkClientLibrary: no server port specified to connect to."); + } + + if (config.SERVER_TCP_PORT !== undefined) { + this.tcp = new TCPClient( + +config.SERVER_TCP_PORT, + config.SERVER_ADDRESS, + config.MAGIC_VALUE, + config.WSS, + ); + await this.tcp.connect(); + } + + if (config.SERVER_UDP_PORT !== undefined) { + this.udp = new UDPClient( + +config.SERVER_UDP_PORT, + config.SERVER_ADDRESS, + config.MAGIC_VALUE, + config.WSS, + ); + await this.udp.connect(); + } + } + + public override expose(): NetworkClientContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + get tcp() { + if (!library.tcp) throw new Error("TCP isn't defined"); + return library.tcp; + }, + get udp() { + if (!library.udp) throw new Error("UDP isn't defined"); + return library.udp; + }, + }; + } +} diff --git a/packages/network-client/src/config.client.network.ts b/modules/network/src/client/config.client.network.ts similarity index 83% rename from packages/network-client/src/config.client.network.ts rename to modules/network/src/client/config.client.network.ts index e84edc03..9b953e0b 100644 --- a/packages/network-client/src/config.client.network.ts +++ b/modules/network/src/client/config.client.network.ts @@ -7,15 +7,13 @@ import { IsOptional, IsPort, TransformToBoolean, -} from "@nanoforge-dev/config"; +} from "@nanoforge-dev/env"; /** * Environment-variable configuration for `NetworkClientLibrary`. * * @remarks - * Resolved automatically by `IConfigRegistry.registerConfig` during `__init`. - * Set these variables in the environment (or pass them via - * `IRunClientOptions.env`) before running the application. + * Resolved via `registerEnv(ClientConfigNetwork, ctx.env)` during `__init`. */ export class ClientConfigNetwork { /** diff --git a/modules/network/src/client/context-augmentation.ts b/modules/network/src/client/context-augmentation.ts new file mode 100644 index 00000000..110a2c7c --- /dev/null +++ b/modules/network/src/client/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { NetworkClientContextApi } from "./network-client-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + network: NetworkClientContextApi; + } +} diff --git a/packages/network-client/src/index.ts b/modules/network/src/client/index.ts similarity index 50% rename from packages/network-client/src/index.ts rename to modules/network/src/client/index.ts index f5016dc5..56c29bd9 100644 --- a/packages/network-client/src/index.ts +++ b/modules/network/src/client/index.ts @@ -1,3 +1,7 @@ +import "./context-augmentation"; + export { NetworkClientLibrary } from "./client.network.library"; +export { ClientConfigNetwork } from "./config.client.network"; +export type { NetworkClientContextApi } from "./network-client-context.type"; export type { TCPClient } from "./tcp.client.network"; export type { UDPClient } from "./udp.client.network"; diff --git a/modules/network/src/client/network-client-context.type.ts b/modules/network/src/client/network-client-context.type.ts new file mode 100644 index 00000000..fd102c0d --- /dev/null +++ b/modules/network/src/client/network-client-context.type.ts @@ -0,0 +1,10 @@ +import type { TCPClient } from "./tcp.client.network"; +import type { UDPClient } from "./udp.client.network"; + +/** Public surface of `NetworkClientLibrary`, exposed on `Context.network`. */ +export interface NetworkClientContextApi { + /** Reliable, ordered WebSocket connection. Only set when `SERVER_TCP_PORT` was configured. */ + readonly tcp: TCPClient; + /** Unreliable, unordered WebRTC data-channel connection. Only set when `SERVER_UDP_PORT` was configured. */ + readonly udp: UDPClient; +} diff --git a/packages/network-client/src/tcp.client.network.ts b/modules/network/src/client/tcp.client.network.ts similarity index 100% rename from packages/network-client/src/tcp.client.network.ts rename to modules/network/src/client/tcp.client.network.ts diff --git a/packages/network-client/src/udp.client.network.ts b/modules/network/src/client/udp.client.network.ts similarity index 100% rename from packages/network-client/src/udp.client.network.ts rename to modules/network/src/client/udp.client.network.ts diff --git a/packages/network-client/src/utils.ts b/modules/network/src/client/utils.ts similarity index 100% rename from packages/network-client/src/utils.ts rename to modules/network/src/client/utils.ts diff --git a/packages/network-server/src/config.server.network.ts b/modules/network/src/server/config.server.network.ts similarity index 86% rename from packages/network-server/src/config.server.network.ts rename to modules/network/src/server/config.server.network.ts index ec8c6ede..300bda37 100644 --- a/packages/network-server/src/config.server.network.ts +++ b/modules/network/src/server/config.server.network.ts @@ -6,15 +6,13 @@ import { IsOptional, IsPort, IsString, -} from "@nanoforge-dev/config"; +} from "@nanoforge-dev/env"; /** * Environment-variable configuration for `NetworkServerLibrary`. * * @remarks - * Resolved automatically by `IConfigRegistry.registerConfig` during `__init`. - * Set these variables in the environment (or pass them via - * `IRunServerOptions.env`) before running the application. + * Resolved via `registerEnv(ServerConfigNetwork, ctx.env)` during `__init`. */ export class ServerConfigNetwork { /** diff --git a/modules/network/src/server/context-augmentation.ts b/modules/network/src/server/context-augmentation.ts new file mode 100644 index 00000000..426f9667 --- /dev/null +++ b/modules/network/src/server/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { NetworkServerContextApi } from "./network-server-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + network: NetworkServerContextApi; + } +} diff --git a/packages/network-server/src/index.ts b/modules/network/src/server/index.ts similarity index 50% rename from packages/network-server/src/index.ts rename to modules/network/src/server/index.ts index 96a56a99..a749ff50 100644 --- a/packages/network-server/src/index.ts +++ b/modules/network/src/server/index.ts @@ -1,3 +1,7 @@ +import "./context-augmentation"; + +export { ServerConfigNetwork } from "./config.server.network"; +export type { NetworkServerContextApi } from "./network-server-context.type"; export { NetworkServerLibrary } from "./server.network.library"; export type { TCPServer } from "./tcp.server.network"; export type { UDPServer } from "./udp.server.network"; diff --git a/modules/network/src/server/network-server-context.type.ts b/modules/network/src/server/network-server-context.type.ts new file mode 100644 index 00000000..cf218c57 --- /dev/null +++ b/modules/network/src/server/network-server-context.type.ts @@ -0,0 +1,10 @@ +import type { TCPServer } from "./tcp.server.network"; +import type { UDPServer } from "./udp.server.network"; + +/** Public surface of `NetworkServerLibrary`, exposed on `Context.network`. */ +export interface NetworkServerContextApi { + /** Reliable, ordered WebSocket server. Only set when `LISTENING_TCP_PORT` was configured. */ + readonly tcp: TCPServer; + /** Unreliable, unordered WebRTC data-channel server. Only set when `LISTENING_UDP_PORT` was configured. */ + readonly udp: UDPServer; +} diff --git a/packages/network-server/src/server.network.library.ts b/modules/network/src/server/server.network.library.ts similarity index 50% rename from packages/network-server/src/server.network.library.ts rename to modules/network/src/server/server.network.library.ts index a422970d..90be83be 100644 --- a/packages/network-server/src/server.network.library.ts +++ b/modules/network/src/server/server.network.library.ts @@ -1,6 +1,8 @@ -import { BaseNetworkLibrary, type InitContext, NfConfigException } from "@nanoforge-dev/common"; +import { type InitContext, Library, defineLibraryKey } from "@nanoforge-dev/common"; +import { registerEnv } from "@nanoforge-dev/env"; import { ServerConfigNetwork } from "./config.server.network"; +import type { NetworkServerContextApi } from "./network-server-context.type"; import { TCPServer } from "./tcp.server.network"; import { UDPServer } from "./udp.server.network"; @@ -8,13 +10,8 @@ import { UDPServer } from "./udp.server.network"; * Built-in network library for server-side applications. * * @remarks - * Reads network configuration from the environment via - * `ServerConfigNetwork` and starts TCP (WebSocket) and/or UDP (WebRTC) - * servers. Register with: - * - * ```ts - * server.useNetwork(new NetworkServerLibrary()); - * ``` + * Reads network configuration from the environment via `ServerConfigNetwork` + * and starts TCP (WebSocket) and/or UDP (WebRTC) servers. * * Configuration (via environment variables): * - `LISTENING_INTERFACE` — bind address (default: `"0.0.0.0"`). @@ -22,47 +19,27 @@ import { UDPServer } from "./udp.server.network"; * - `LISTENING_UDP_PORT` — signaling listen port for UDP (optional). * - `MAGIC_VALUE` — packet framing delimiter (default: `"PACKET_END"`). * - `WSS_CERT` / `WSS_KEY` — paths to TLS certificate and key files for WSS (optional). - * - * After `init`, access the servers via `tcp` and `udp`. */ -export class NetworkServerLibrary extends BaseNetworkLibrary { - /** - * Unreliable, unordered WebRTC data-channel server for connected clients. - * - * @remarks - * Only available when `LISTENING_UDP_PORT` was specified in the environment. - */ - public udp!: UDPServer; +export class NetworkServerLibrary extends Library { + readonly key = defineLibraryKey("network"); - /** - * Reliable, ordered WebSocket-based server for connected clients. - * - * @remarks - * Only available when `LISTENING_TCP_PORT` was specified in the environment. - */ - public tcp!: TCPServer; - - /** @internal */ - get __name(): string { - return "NetworkServerLibrary"; - } + /** Only set when `LISTENING_TCP_PORT` was configured. */ + public tcp?: TCPServer; + /** Only set when `LISTENING_UDP_PORT` was configured. */ + public udp?: UDPServer; - /** @internal */ - public override async __init(context: InitContext): Promise { - const config: ServerConfigNetwork = await context.config.registerConfig(ServerConfigNetwork); + public override async __init(ctx: InitContext): Promise { + const config = await registerEnv(ServerConfigNetwork, ctx.env); - if (config.LISTENING_INTERFACE === undefined) { - throw new NfConfigException("No listenning address provided", this.__name); - } if (config.LISTENING_TCP_PORT === undefined && config.LISTENING_UDP_PORT === undefined) { - throw new NfConfigException("No listenning port specified", this.__name); + throw new Error("NetworkServerLibrary: no listening port specified."); } if ( (config.WSS_CERT !== undefined && config.WSS_KEY === undefined) || (config.WSS_CERT === undefined && config.WSS_KEY !== undefined) ) { - throw new NfConfigException("Both cert and key must be provided together", this.__name); + throw new Error("NetworkServerLibrary: both WSS_CERT and WSS_KEY must be provided together."); } if (config.LISTENING_TCP_PORT !== undefined) { @@ -87,4 +64,19 @@ export class NetworkServerLibrary extends BaseNetworkLibrary { this.udp.listen(); } } + + public override expose(): NetworkServerContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + get tcp() { + if (!library.tcp) throw new Error("TCP isn't defined"); + return library.tcp; + }, + get udp() { + if (!library.udp) throw new Error("UDP isn't defined"); + return library.udp; + }, + }; + } } diff --git a/packages/network-server/src/tcp.server.network.ts b/modules/network/src/server/tcp.server.network.ts similarity index 100% rename from packages/network-server/src/tcp.server.network.ts rename to modules/network/src/server/tcp.server.network.ts diff --git a/packages/network-server/src/udp.server.network.ts b/modules/network/src/server/udp.server.network.ts similarity index 100% rename from packages/network-server/src/udp.server.network.ts rename to modules/network/src/server/udp.server.network.ts diff --git a/packages/network-server/src/utils.ts b/modules/network/src/server/utils.ts similarity index 100% rename from packages/network-server/src/utils.ts rename to modules/network/src/server/utils.ts diff --git a/modules/network/src/server/wrtc.d.ts b/modules/network/src/server/wrtc.d.ts new file mode 100644 index 00000000..5712fdf2 --- /dev/null +++ b/modules/network/src/server/wrtc.d.ts @@ -0,0 +1 @@ +declare module "wrtc"; diff --git a/packages/network-client/test/client.network.library.spec.ts b/modules/network/test/client/client.network.library.spec.ts similarity index 63% rename from packages/network-client/test/client.network.library.spec.ts rename to modules/network/test/client/client.network.library.spec.ts index cede52a9..c7ec8ef2 100644 --- a/packages/network-client/test/client.network.library.spec.ts +++ b/modules/network/test/client/client.network.library.spec.ts @@ -1,14 +1,13 @@ -import { type InitContext, NfConfigException } from "@nanoforge-dev/common"; +import type { InitContext } from "@nanoforge-dev/common"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { NetworkClientLibrary } from "../src"; +import { NetworkClientLibrary } from "../../src/client"; -const makeContext = (config: Record) => - ({ - config: { - registerConfig: vi.fn().mockResolvedValue(config), - }, - }) as unknown as InitContext; +const makeInitContext = (env: Record): InitContext => ({ + vars: { get: () => undefined, set: () => {} }, + env, + files: new Map(), +}); describe("NetworkClientLibrary", () => { beforeEach(() => { @@ -53,21 +52,21 @@ describe("NetworkClientLibrary", () => { }); describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new NetworkClientLibrary().__name).toBe("NetworkClientLibrary"); + it("should expose the reserved 'network' key", () => { + expect(new NetworkClientLibrary().key).toBe("network"); }); }); describe("config validation", () => { - it("should throw NfConfigException when neither TCP nor UDP port is provided", async () => { - const ctx = makeContext({ SERVER_ADDRESS: "127.0.0.1", MAGIC_VALUE: "END" }); - await expect(new NetworkClientLibrary().__init(ctx)).rejects.toThrow(NfConfigException); + it("should throw when neither TCP nor UDP port is provided", async () => { + const ctx = makeInitContext({ SERVER_ADDRESS: "127.0.0.1", MAGIC_VALUE: "END" }); + await expect(new NetworkClientLibrary().__init(ctx)).rejects.toThrow(); }); }); describe("initialization", () => { it("should initialize a TCP client when only SERVER_TCP_PORT is provided", async () => { - const ctx = makeContext({ + const ctx = makeInitContext({ SERVER_TCP_PORT: "8080", SERVER_ADDRESS: "127.0.0.1", MAGIC_VALUE: "END", @@ -79,7 +78,7 @@ describe("NetworkClientLibrary", () => { }); it("should initialize a UDP client when only SERVER_UDP_PORT is provided", async () => { - const ctx = makeContext({ + const ctx = makeInitContext({ SERVER_UDP_PORT: "8081", SERVER_ADDRESS: "127.0.0.1", MAGIC_VALUE: "END", @@ -91,7 +90,7 @@ describe("NetworkClientLibrary", () => { }); it("should initialize both TCP and UDP clients when both ports are provided", async () => { - const ctx = makeContext({ + const ctx = makeInitContext({ SERVER_TCP_PORT: "8080", SERVER_UDP_PORT: "8081", SERVER_ADDRESS: "127.0.0.1", @@ -102,5 +101,25 @@ describe("NetworkClientLibrary", () => { expect(lib.tcp).toBeDefined(); expect(lib.udp).toBeDefined(); }); + + it("should default MAGIC_VALUE and WSS when not provided", async () => { + const ctx = makeInitContext({ SERVER_TCP_PORT: "8080", SERVER_ADDRESS: "127.0.0.1" }); + const lib = new NetworkClientLibrary(); + await expect(lib.__init(ctx)).resolves.toBeUndefined(); + }); + }); + + describe("expose", () => { + it("returns the tcp/udp clients", async () => { + const ctx = makeInitContext({ + SERVER_TCP_PORT: "8080", + SERVER_ADDRESS: "127.0.0.1", + MAGIC_VALUE: "END", + }); + const lib = new NetworkClientLibrary(); + await lib.__init(ctx); + expect(lib.expose().tcp).toBe(lib.tcp); + expect(lib.expose().udp).toBeUndefined(); + }); }); }); diff --git a/packages/network-client/test/tcp.client.spec.ts b/modules/network/test/client/tcp.client.spec.ts similarity index 97% rename from packages/network-client/test/tcp.client.spec.ts rename to modules/network/test/client/tcp.client.spec.ts index 7790c2cf..67f94733 100644 --- a/packages/network-client/test/tcp.client.spec.ts +++ b/modules/network/test/client/tcp.client.spec.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { TCPClient } from "../src/tcp.client.network"; +import { TCPClient } from "../../src/client/tcp.client.network"; const makeWsMock = (readyState = 0) => ({ readyState, diff --git a/packages/network-client/test/udp.client.spec.ts b/modules/network/test/client/udp.client.spec.ts similarity index 96% rename from packages/network-client/test/udp.client.spec.ts rename to modules/network/test/client/udp.client.spec.ts index ae76a8ca..9bc9196f 100644 --- a/packages/network-client/test/udp.client.spec.ts +++ b/modules/network/test/client/udp.client.spec.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { UDPClient } from "../src/udp.client.network"; +import { UDPClient } from "../../src/client/udp.client.network"; describe("UDPClient", () => { beforeEach(() => { diff --git a/packages/network-client/test/utils.spec.ts b/modules/network/test/client/utils.spec.ts similarity index 97% rename from packages/network-client/test/utils.spec.ts rename to modules/network/test/client/utils.spec.ts index fb846764..4e0d9792 100644 --- a/packages/network-client/test/utils.spec.ts +++ b/modules/network/test/client/utils.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import { buildMagicPacket, parsePacketsFromChunks } from "../src/utils"; +import { buildMagicPacket, parsePacketsFromChunks } from "../../src/client/utils"; const magic = new TextEncoder().encode("END"); diff --git a/packages/network-server/test/server.network.library.spec.ts b/modules/network/test/server/server.network.library.spec.ts similarity index 52% rename from packages/network-server/test/server.network.library.spec.ts rename to modules/network/test/server/server.network.library.spec.ts index 4a0f1a84..63581d85 100644 --- a/packages/network-server/test/server.network.library.spec.ts +++ b/modules/network/test/server/server.network.library.spec.ts @@ -1,7 +1,7 @@ -import { type InitContext, NfConfigException } from "@nanoforge-dev/common"; +import type { InitContext } from "@nanoforge-dev/common"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { NetworkServerLibrary } from "../src"; +import { NetworkServerLibrary } from "../../src/server"; vi.mock("ws", () => ({ WebSocketServer: vi.fn(function (this: any) { @@ -18,12 +18,11 @@ vi.mock("wrtc", () => ({ }), })); -const makeContext = (config: Record) => - ({ - config: { - registerConfig: vi.fn().mockResolvedValue(config), - }, - }) as unknown as InitContext; +const makeInitContext = (env: Record): InitContext => ({ + vars: { get: () => undefined, set: () => {} }, + env, + files: new Map(), +}); describe("NetworkServerLibrary", () => { afterEach(() => { @@ -31,30 +30,26 @@ describe("NetworkServerLibrary", () => { }); describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new NetworkServerLibrary().__name).toBe("NetworkServerLibrary"); + it("should expose the reserved 'network' key", () => { + expect(new NetworkServerLibrary().key).toBe("network"); }); }); describe("config validation", () => { - it("should throw NfConfigException when LISTENING_INTERFACE is not provided", async () => { - const ctx = makeContext({ LISTENING_TCP_PORT: "9000", MAGIC_VALUE: "END" }); - await expect(new NetworkServerLibrary().__init(ctx)).rejects.toThrow(NfConfigException); + it("should throw when neither TCP nor UDP port is provided", async () => { + const ctx = makeInitContext({ MAGIC_VALUE: "END" }); + await expect(new NetworkServerLibrary().__init(ctx)).rejects.toThrow(); }); - it("should throw NfConfigException when neither TCP nor UDP port is provided", async () => { - const ctx = makeContext({ LISTENING_INTERFACE: "0.0.0.0", MAGIC_VALUE: "END" }); - await expect(new NetworkServerLibrary().__init(ctx)).rejects.toThrow(NfConfigException); + it("should throw when only WSS_CERT is provided without WSS_KEY", async () => { + const ctx = makeInitContext({ LISTENING_TCP_PORT: "9000", WSS_CERT: "cert.pem" }); + await expect(new NetworkServerLibrary().__init(ctx)).rejects.toThrow(); }); }); describe("initialization", () => { it("should initialize a TCP server when only LISTENING_TCP_PORT is provided", async () => { - const ctx = makeContext({ - LISTENING_TCP_PORT: "9000", - LISTENING_INTERFACE: "0.0.0.0", - MAGIC_VALUE: "END", - }); + const ctx = makeInitContext({ LISTENING_TCP_PORT: "9000", MAGIC_VALUE: "END" }); const lib = new NetworkServerLibrary(); await lib.__init(ctx); expect(lib.tcp).toBeDefined(); @@ -62,11 +57,7 @@ describe("NetworkServerLibrary", () => { }); it("should initialize a UDP server when only LISTENING_UDP_PORT is provided", async () => { - const ctx = makeContext({ - LISTENING_UDP_PORT: "9001", - LISTENING_INTERFACE: "0.0.0.0", - MAGIC_VALUE: "END", - }); + const ctx = makeInitContext({ LISTENING_UDP_PORT: "9001", MAGIC_VALUE: "END" }); const lib = new NetworkServerLibrary(); await lib.__init(ctx); expect(lib.udp).toBeDefined(); @@ -74,10 +65,9 @@ describe("NetworkServerLibrary", () => { }); it("should initialize both TCP and UDP servers when both ports are provided", async () => { - const ctx = makeContext({ + const ctx = makeInitContext({ LISTENING_TCP_PORT: "9000", LISTENING_UDP_PORT: "9001", - LISTENING_INTERFACE: "0.0.0.0", MAGIC_VALUE: "END", }); const lib = new NetworkServerLibrary(); @@ -85,5 +75,21 @@ describe("NetworkServerLibrary", () => { expect(lib.tcp).toBeDefined(); expect(lib.udp).toBeDefined(); }); + + it("should default LISTENING_INTERFACE to 0.0.0.0 and MAGIC_VALUE when not provided", async () => { + const ctx = makeInitContext({ LISTENING_TCP_PORT: "9000" }); + const lib = new NetworkServerLibrary(); + await expect(lib.__init(ctx)).resolves.toBeUndefined(); + }); + }); + + describe("expose", () => { + it("returns the tcp/udp servers", async () => { + const ctx = makeInitContext({ LISTENING_TCP_PORT: "9000" }); + const lib = new NetworkServerLibrary(); + await lib.__init(ctx); + expect(lib.expose().tcp).toBe(lib.tcp); + expect(lib.expose().udp).toBeUndefined(); + }); }); }); diff --git a/packages/network-server/test/tcp.server.spec.ts b/modules/network/test/server/tcp.server.spec.ts similarity index 98% rename from packages/network-server/test/tcp.server.spec.ts rename to modules/network/test/server/tcp.server.spec.ts index 64a4a292..f506f484 100644 --- a/packages/network-server/test/tcp.server.spec.ts +++ b/modules/network/test/server/tcp.server.spec.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from "vitest"; -import { TCPServer } from "../src/tcp.server.network"; +import { TCPServer } from "../../src/server/tcp.server.network"; vi.mock("ws", () => ({ WebSocketServer: vi.fn(function (this: any) { diff --git a/packages/network-server/test/udp.server.spec.ts b/modules/network/test/server/udp.server.spec.ts similarity index 97% rename from packages/network-server/test/udp.server.spec.ts rename to modules/network/test/server/udp.server.spec.ts index 7dd4ccf6..68bfd039 100644 --- a/packages/network-server/test/udp.server.spec.ts +++ b/modules/network/test/server/udp.server.spec.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from "vitest"; -import { UDPServer } from "../src/udp.server.network"; +import { UDPServer } from "../../src/server/udp.server.network"; vi.mock("ws", () => ({ WebSocketServer: vi.fn(function (this: any) { diff --git a/packages/network-server/test/utils.spec.ts b/modules/network/test/server/utils.spec.ts similarity index 97% rename from packages/network-server/test/utils.spec.ts rename to modules/network/test/server/utils.spec.ts index eb08205d..e64312b8 100644 --- a/packages/network-server/test/utils.spec.ts +++ b/modules/network/test/server/utils.spec.ts @@ -1,6 +1,10 @@ import { describe, expect, it } from "vitest"; -import { buildMagicPacket, parsePacketsFromChunks, rawDataToUint8Array } from "../src/utils"; +import { + buildMagicPacket, + parsePacketsFromChunks, + rawDataToUint8Array, +} from "../../src/server/utils"; const magic = new TextEncoder().encode("END"); diff --git a/modules/network/tsconfig.client.json b/modules/network/tsconfig.client.json new file mode 100644 index 00000000..22c56907 --- /dev/null +++ b/modules/network/tsconfig.client.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "./tsconfig.json", + "include": ["src/client/**/*.ts"], + "compilerOptions": { + "declaration": true + } +} diff --git a/packages/graphics-2d-editor/tsconfig.json b/modules/network/tsconfig.json similarity index 100% rename from packages/graphics-2d-editor/tsconfig.json rename to modules/network/tsconfig.json diff --git a/modules/network/tsconfig.server.json b/modules/network/tsconfig.server.json new file mode 100644 index 00000000..cc4b2420 --- /dev/null +++ b/modules/network/tsconfig.server.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "./tsconfig.json", + "include": ["src/server/**/*.ts"], + "compilerOptions": { + "declaration": true + } +} diff --git a/packages/graphics-2d-editor/tsconfig.spec.json b/modules/network/tsconfig.spec.json similarity index 100% rename from packages/graphics-2d-editor/tsconfig.spec.json rename to modules/network/tsconfig.spec.json diff --git a/packages/ecs-server/tsdoc.json b/modules/network/tsdoc.json similarity index 100% rename from packages/ecs-server/tsdoc.json rename to modules/network/tsdoc.json diff --git a/modules/network/tsdown.config.ts b/modules/network/tsdown.config.ts new file mode 100644 index 00000000..8985c61e --- /dev/null +++ b/modules/network/tsdown.config.ts @@ -0,0 +1,14 @@ +import { createTsdownConfig } from "../../tsdown.config"; + +export default [ + createTsdownConfig({ + entry: "src/client/index.ts", + outDir: "dist/client", + tsconfig: "tsconfig.client.json", + }), + createTsdownConfig({ + entry: "src/server/index.ts", + outDir: "dist/server", + tsconfig: "tsconfig.server.json", + }), +]; From a874f6dcb83b2fab9bb784ad4b1c4ebd228222f5 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 11:49:46 +0200 Subject: [PATCH 04/12] chore: remove unused files (#428) --- packages/asset-manager/.cliff-jumperrc.json | 8 - packages/asset-manager/.nvmrc | 1 - .../src/asset-manager.library.ts | 68 ---- packages/asset-manager/src/index.ts | 1 - .../test/asset-manager.library.spec.ts | 84 ----- packages/config/.nvmrc | 1 - packages/config/CHANGELOG.md | 63 ---- packages/config/README.md | 155 --------- packages/config/package.json | 88 ----- packages/config/src/default.ts | 28 -- packages/config/src/exports/index.ts | 2 - packages/config/src/index.ts | 4 - packages/config/src/transformers/index.ts | 1 - packages/config/src/validators/index.ts | 1 - packages/core-editor/.nvmrc | 1 - packages/core-editor/CHANGELOG.md | 57 --- packages/core-editor/README.md | 52 --- packages/core-editor/mint-tsdocs.config.json | 13 - packages/core-editor/package.json | 94 ----- .../src/application/nanoforge-application.ts | 99 ------ .../src/application/nanoforge-client.ts | 43 --- .../src/application/nanoforge-factory.ts | 43 --- .../src/application/nanoforge-server.ts | 10 - .../common/context/contexts/init.context.ts | 28 -- .../src/common/context/event-emitter.ts | 30 -- .../src/common/context/event-emitter.type.ts | 76 ---- .../src/common/context/events/core-events.ts | 25 -- .../common/context/events/editor-events.ts | 11 - .../core-editor/src/common/context/index.ts | 3 - .../src/common/context/options.type.ts | 60 ---- .../src/common/context/save.type.ts | 71 ---- packages/core-editor/src/core/core.ts | 115 ------ .../core-editor/src/editor/core-editor.ts | 103 ------ packages/core-editor/src/index.ts | 41 --- .../core-editor/test/editor-feature.spec.ts | 161 --------- .../core-editor/test/helpers/event-emitter.ts | 82 ----- packages/ecs-client/.gitignore | 276 --------------- packages/ecs-client/.nvmrc | 1 - packages/ecs-client/.prettierignore | 13 - packages/ecs-client/CHANGELOG.md | 75 ---- packages/ecs-client/Makefile | 47 --- packages/ecs-client/README.md | 125 ------- packages/ecs-client/mint-tsdocs.config.json | 13 - packages/ecs-client/src/ecs-client-library.ts | 40 --- packages/ecs-client/src/index.ts | 14 - .../test/ecs-client-library.spec.ts | 176 ---------- packages/ecs-lib/.gitignore | 280 --------------- packages/ecs-lib/.nvmrc | 1 - packages/ecs-lib/.prettierignore | 14 - packages/ecs-lib/CHANGELOG.md | 86 ----- packages/ecs-lib/Makefile | 42 --- packages/ecs-lib/README.md | 56 --- packages/ecs-lib/eslint.config.js | 3 - packages/ecs-lib/package.json | 93 ----- packages/ecs-lib/src/ecs-library.abstract.ts | 65 ---- packages/ecs-lib/src/editor-manifest.type.ts | 142 -------- packages/ecs-lib/src/index.ts | 3 - packages/ecs-lib/test/Registry.spec.ts | 158 --------- packages/ecs-lib/test/SparseArray.spec.ts | 94 ----- packages/ecs-lib/test/Zipper.spec.ts | 131 ------- packages/ecs-server/.nvmrc | 1 - packages/ecs-server/CHANGELOG.md | 83 ----- packages/ecs-server/Makefile | 47 --- packages/ecs-server/README.md | 125 ------- packages/ecs-server/package.json | 98 ------ packages/ecs-server/src/ecs-server-library.ts | 40 --- packages/ecs-server/src/index.ts | 17 - .../test/ecs-server-library.spec.ts | 176 ---------- packages/ecs-server/tsconfig.json | 16 - .../graphics-2d-editor/.cliff-jumperrc.json | 8 - packages/graphics-2d-editor/.nvmrc | 1 - packages/graphics-2d-editor/CHANGELOG.md | 17 - packages/graphics-2d-editor/README.md | 98 ------ packages/graphics-2d-editor/package.json | 91 ----- .../src/graphics-2d-editor.library.ts | 63 ---- packages/graphics-2d-editor/src/index.ts | 1 - packages/graphics-2d/.nvmrc | 1 - packages/graphics-2d/CHANGELOG.md | 101 ------ .../graphics-2d/src/graphics-2d.library.ts | 81 ----- packages/graphics-2d/src/index.ts | 2 - .../test/graphics-2d.library.spec.ts | 45 --- packages/graphics-2d/tsdown.config.ts | 3 - packages/input/.nvmrc | 1 - packages/input/CHANGELOG.md | 71 ---- packages/input/LICENSE | 21 -- packages/input/src/index.ts | 2 - packages/input/src/input-handler.ts | 180 ---------- packages/input/src/input.library.ts | 142 -------- packages/input/test/input.library.spec.ts | 327 ------------------ packages/input/tsdown.config.ts | 3 - packages/music/.nvmrc | 1 - packages/music/CHANGELOG.md | 62 ---- packages/music/LICENSE | 21 -- packages/music/cliff.toml | 79 ----- packages/music/src/index.ts | 1 - packages/music/src/music.library.ts | 98 ------ packages/music/tsdoc.json | 14 - packages/music/tsdown.config.ts | 3 - packages/network-client/.cliff-jumperrc.json | 8 - packages/network-client/.nvmrc | 1 - packages/network-client/CHANGELOG.md | 64 ---- packages/network-client/LICENSE | 21 -- packages/network-client/README.md | 97 ------ packages/network-client/cliff.toml | 79 ----- .../network-client/mint-tsdocs.config.json | 13 - packages/network-client/prettier.config.js | 3 - .../src/client.network.library.ts | 78 ----- packages/network-client/tsconfig.json | 15 - packages/network-client/tsdoc.json | 14 - packages/network-client/tsdown.config.ts | 3 - packages/network-server/.cliff-jumperrc.json | 8 - packages/network-server/.nvmrc | 1 - packages/network-server/CHANGELOG.md | 60 ---- packages/network-server/LICENSE | 21 -- packages/network-server/README.md | 99 ------ packages/network-server/cliff.toml | 79 ----- packages/network-server/eslint.config.js | 3 - .../network-server/mint-tsdocs.config.json | 13 - packages/network-server/prettier.config.js | 3 - packages/network-server/src/wrtc.d.ts | 1 - packages/network-server/tsconfig.json | 16 - packages/network-server/tsdoc.json | 14 - packages/network-server/tsdown.config.ts | 3 - packages/sound/.nvmrc | 1 - packages/sound/.prettierignore | 11 - packages/sound/CHANGELOG.md | 61 ---- packages/sound/LICENSE | 21 -- packages/sound/cliff.toml | 79 ----- packages/sound/eslint.config.js | 3 - packages/sound/prettier.config.js | 3 - packages/sound/src/index.ts | 1 - packages/sound/src/sound.library.ts | 94 ----- packages/sound/tsconfig.json | 15 - packages/sound/tsdoc.json | 14 - packages/sound/tsdown.config.ts | 3 - 135 files changed, 6835 deletions(-) delete mode 100644 packages/asset-manager/.cliff-jumperrc.json delete mode 100644 packages/asset-manager/.nvmrc delete mode 100644 packages/asset-manager/src/asset-manager.library.ts delete mode 100644 packages/asset-manager/src/index.ts delete mode 100644 packages/asset-manager/test/asset-manager.library.spec.ts delete mode 100644 packages/config/.nvmrc delete mode 100644 packages/config/CHANGELOG.md delete mode 100644 packages/config/README.md delete mode 100644 packages/config/package.json delete mode 100644 packages/config/src/default.ts delete mode 100644 packages/config/src/exports/index.ts delete mode 100644 packages/config/src/index.ts delete mode 100644 packages/config/src/transformers/index.ts delete mode 100644 packages/config/src/validators/index.ts delete mode 100644 packages/core-editor/.nvmrc delete mode 100644 packages/core-editor/CHANGELOG.md delete mode 100644 packages/core-editor/README.md delete mode 100644 packages/core-editor/mint-tsdocs.config.json delete mode 100644 packages/core-editor/package.json delete mode 100644 packages/core-editor/src/application/nanoforge-application.ts delete mode 100644 packages/core-editor/src/application/nanoforge-client.ts delete mode 100644 packages/core-editor/src/application/nanoforge-factory.ts delete mode 100644 packages/core-editor/src/application/nanoforge-server.ts delete mode 100644 packages/core-editor/src/common/context/contexts/init.context.ts delete mode 100644 packages/core-editor/src/common/context/event-emitter.ts delete mode 100644 packages/core-editor/src/common/context/event-emitter.type.ts delete mode 100644 packages/core-editor/src/common/context/events/core-events.ts delete mode 100644 packages/core-editor/src/common/context/events/editor-events.ts delete mode 100644 packages/core-editor/src/common/context/index.ts delete mode 100644 packages/core-editor/src/common/context/options.type.ts delete mode 100644 packages/core-editor/src/common/context/save.type.ts delete mode 100644 packages/core-editor/src/core/core.ts delete mode 100644 packages/core-editor/src/editor/core-editor.ts delete mode 100644 packages/core-editor/src/index.ts delete mode 100644 packages/core-editor/test/editor-feature.spec.ts delete mode 100644 packages/core-editor/test/helpers/event-emitter.ts delete mode 100644 packages/ecs-client/.gitignore delete mode 100644 packages/ecs-client/.nvmrc delete mode 100644 packages/ecs-client/.prettierignore delete mode 100644 packages/ecs-client/CHANGELOG.md delete mode 100644 packages/ecs-client/Makefile delete mode 100644 packages/ecs-client/README.md delete mode 100644 packages/ecs-client/mint-tsdocs.config.json delete mode 100644 packages/ecs-client/src/ecs-client-library.ts delete mode 100644 packages/ecs-client/src/index.ts delete mode 100644 packages/ecs-client/test/ecs-client-library.spec.ts delete mode 100644 packages/ecs-lib/.gitignore delete mode 100644 packages/ecs-lib/.nvmrc delete mode 100644 packages/ecs-lib/.prettierignore delete mode 100644 packages/ecs-lib/CHANGELOG.md delete mode 100644 packages/ecs-lib/Makefile delete mode 100644 packages/ecs-lib/README.md delete mode 100644 packages/ecs-lib/eslint.config.js delete mode 100644 packages/ecs-lib/package.json delete mode 100644 packages/ecs-lib/src/ecs-library.abstract.ts delete mode 100644 packages/ecs-lib/src/editor-manifest.type.ts delete mode 100644 packages/ecs-lib/src/index.ts delete mode 100644 packages/ecs-lib/test/Registry.spec.ts delete mode 100644 packages/ecs-lib/test/SparseArray.spec.ts delete mode 100644 packages/ecs-lib/test/Zipper.spec.ts delete mode 100644 packages/ecs-server/.nvmrc delete mode 100644 packages/ecs-server/CHANGELOG.md delete mode 100644 packages/ecs-server/Makefile delete mode 100644 packages/ecs-server/README.md delete mode 100644 packages/ecs-server/package.json delete mode 100644 packages/ecs-server/src/ecs-server-library.ts delete mode 100644 packages/ecs-server/src/index.ts delete mode 100644 packages/ecs-server/test/ecs-server-library.spec.ts delete mode 100644 packages/ecs-server/tsconfig.json delete mode 100644 packages/graphics-2d-editor/.cliff-jumperrc.json delete mode 100644 packages/graphics-2d-editor/.nvmrc delete mode 100644 packages/graphics-2d-editor/CHANGELOG.md delete mode 100644 packages/graphics-2d-editor/README.md delete mode 100644 packages/graphics-2d-editor/package.json delete mode 100644 packages/graphics-2d-editor/src/graphics-2d-editor.library.ts delete mode 100644 packages/graphics-2d-editor/src/index.ts delete mode 100644 packages/graphics-2d/.nvmrc delete mode 100644 packages/graphics-2d/CHANGELOG.md delete mode 100644 packages/graphics-2d/src/graphics-2d.library.ts delete mode 100644 packages/graphics-2d/src/index.ts delete mode 100644 packages/graphics-2d/test/graphics-2d.library.spec.ts delete mode 100644 packages/graphics-2d/tsdown.config.ts delete mode 100644 packages/input/.nvmrc delete mode 100644 packages/input/CHANGELOG.md delete mode 100644 packages/input/LICENSE delete mode 100644 packages/input/src/index.ts delete mode 100644 packages/input/src/input-handler.ts delete mode 100644 packages/input/src/input.library.ts delete mode 100644 packages/input/test/input.library.spec.ts delete mode 100644 packages/input/tsdown.config.ts delete mode 100644 packages/music/.nvmrc delete mode 100644 packages/music/CHANGELOG.md delete mode 100644 packages/music/LICENSE delete mode 100644 packages/music/cliff.toml delete mode 100644 packages/music/src/index.ts delete mode 100644 packages/music/src/music.library.ts delete mode 100644 packages/music/tsdoc.json delete mode 100644 packages/music/tsdown.config.ts delete mode 100644 packages/network-client/.cliff-jumperrc.json delete mode 100644 packages/network-client/.nvmrc delete mode 100644 packages/network-client/CHANGELOG.md delete mode 100644 packages/network-client/LICENSE delete mode 100644 packages/network-client/README.md delete mode 100644 packages/network-client/cliff.toml delete mode 100644 packages/network-client/mint-tsdocs.config.json delete mode 100644 packages/network-client/prettier.config.js delete mode 100644 packages/network-client/src/client.network.library.ts delete mode 100644 packages/network-client/tsconfig.json delete mode 100644 packages/network-client/tsdoc.json delete mode 100644 packages/network-client/tsdown.config.ts delete mode 100644 packages/network-server/.cliff-jumperrc.json delete mode 100644 packages/network-server/.nvmrc delete mode 100644 packages/network-server/CHANGELOG.md delete mode 100644 packages/network-server/LICENSE delete mode 100644 packages/network-server/README.md delete mode 100644 packages/network-server/cliff.toml delete mode 100644 packages/network-server/eslint.config.js delete mode 100644 packages/network-server/mint-tsdocs.config.json delete mode 100644 packages/network-server/prettier.config.js delete mode 100644 packages/network-server/src/wrtc.d.ts delete mode 100644 packages/network-server/tsconfig.json delete mode 100644 packages/network-server/tsdoc.json delete mode 100644 packages/network-server/tsdown.config.ts delete mode 100644 packages/sound/.nvmrc delete mode 100644 packages/sound/.prettierignore delete mode 100644 packages/sound/CHANGELOG.md delete mode 100644 packages/sound/LICENSE delete mode 100644 packages/sound/cliff.toml delete mode 100644 packages/sound/eslint.config.js delete mode 100644 packages/sound/prettier.config.js delete mode 100644 packages/sound/src/index.ts delete mode 100644 packages/sound/src/sound.library.ts delete mode 100644 packages/sound/tsconfig.json delete mode 100644 packages/sound/tsdoc.json delete mode 100644 packages/sound/tsdown.config.ts diff --git a/packages/asset-manager/.cliff-jumperrc.json b/packages/asset-manager/.cliff-jumperrc.json deleted file mode 100644 index 86143c44..00000000 --- a/packages/asset-manager/.cliff-jumperrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "asset-manager", - "org": "nanoforge-dev", - "packagePath": "packages/asset-manager", - "tagTemplate": "{{new-version}}", - "identifierBase": false -} diff --git a/packages/asset-manager/.nvmrc b/packages/asset-manager/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/asset-manager/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/asset-manager/src/asset-manager.library.ts b/packages/asset-manager/src/asset-manager.library.ts deleted file mode 100644 index a162f1dc..00000000 --- a/packages/asset-manager/src/asset-manager.library.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { - BaseAssetManagerLibrary, - type InitContext, - NfFile, - NfNotFound, -} from "@nanoforge-dev/common"; - -/** - * Built-in asset-manager library. - * - * @remarks - * Stores the file map injected by the NanoForge loader (`nf start`) and - * exposes assets via `getAsset`. Register it with the application before - * calling `init`: - * - * ```ts - * const client = NanoforgeFactory.createClient(); - * client.useAssetManager(new AssetManagerLibrary()); - * await client.init(`container, files, env `); - * ``` - * - * File paths are normalised on lookup: leading slashes are collapsed to a - * single `/`, duplicate slashes are removed, and trailing slashes are stripped. - */ -export class AssetManagerLibrary extends BaseAssetManagerLibrary { - private _assets?: Map; - - /** @internal */ - get __name(): string { - return "AssetManagerLibrary"; - } - - /** @internal */ - public async __init(context: InitContext): Promise { - this._assets = context.files; - } - - /** - * Retrieve a registered file asset by its virtual path. - * - * @remarks - * The path is normalised before lookup: leading and duplicate slashes are - * collapsed and trailing slashes are removed. - * - * @param path - Virtual path of the asset (e.g. "/textures/hero.png"). - * @returns An `NfFile` handle for the requested asset, or `undefined` if no asset path is provided. - * @throws `NfNotFound` When no asset is registered at the given path. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public getAsset(path: string): NfFile; - public getAsset(path: "" | undefined): undefined; - public getAsset(path: string | undefined): NfFile | undefined { - if (!this._assets) this.throwNotInitializedError(); - - if (!path) return undefined; - - const res = this._assets.get(this._parsePath(path)); - if (!res) throw new NfNotFound(path, "Asset"); - return new NfFile(res); - } - - private _parsePath(path: string): string { - return path - .replace(/^(\/*)/, "/") - .replaceAll(/(\/+)/g, "/") - .replace(/(\/+)$/, ""); - } -} diff --git a/packages/asset-manager/src/index.ts b/packages/asset-manager/src/index.ts deleted file mode 100644 index b1ecb3a3..00000000 --- a/packages/asset-manager/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AssetManagerLibrary } from "./asset-manager.library"; diff --git a/packages/asset-manager/test/asset-manager.library.spec.ts b/packages/asset-manager/test/asset-manager.library.spec.ts deleted file mode 100644 index f43edbfb..00000000 --- a/packages/asset-manager/test/asset-manager.library.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { type IConfigRegistry, InitContext, NfNotFound } from "@nanoforge-dev/common"; -import { beforeEach, describe, expect, it } from "vitest"; - -import { EditableApplicationContext } from "../../core/src/common/context/contexts/application.editable-context"; -import { EditableLibraryManager } from "../../core/src/common/library/manager/library.manager"; -import { AssetManagerLibrary } from "../src"; - -const makeContext = (files: Map) => { - const libraryManager = new EditableLibraryManager(); - const appContext = new EditableApplicationContext(libraryManager); - const configRegistry = {} as IConfigRegistry; - return new InitContext(appContext, libraryManager, configRegistry, { - // @ts-ignore - container: null, - files, - }); -}; - -const TEST_FILES = new Map([ - ["/test.png", "blob:http://localhost:3000/test.png"], - ["/test.wasm", "blob:http://localhost:3000/test.wasm"], - ["/test.wgsl", "blob:http://localhost:3000/test.wgsl"], -]); - -describe("AssetManagerLibrary", () => { - describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new AssetManagerLibrary().__name).toBe("AssetManagerLibrary"); - }); - }); - - describe("before initialization", () => { - it("should throw when getAsset is called before __init", () => { - const library = new AssetManagerLibrary(); - expect(() => library.getAsset("test.png")).toThrow(); - }); - }); - - describe("getAsset", () => { - let library: AssetManagerLibrary; - - beforeEach(async () => { - library = new AssetManagerLibrary(); - await library.__init(makeContext(TEST_FILES)); - }); - - it("should return the correct path for a png asset", () => { - expect(library.getAsset("test.png").path).toBe("blob:http://localhost:3000/test.png"); - }); - - it("should return the correct path for a wasm asset", () => { - expect(library.getAsset("test.wasm").path).toBe("blob:http://localhost:3000/test.wasm"); - }); - - it("should return the correct path for a wgsl asset", () => { - expect(library.getAsset("test.wgsl").path).toBe("blob:http://localhost:3000/test.wgsl"); - }); - - it("should normalize path with a leading slash", () => { - expect(library.getAsset("/test.png").path).toBe("blob:http://localhost:3000/test.png"); - }); - - it("should normalize path with multiple leading slashes", () => { - expect(library.getAsset("//test.png").path).toBe("blob:http://localhost:3000/test.png"); - }); - - it("should throw NfNotFound for an unknown asset", () => { - expect(() => library.getAsset("unknown.png")).toThrow(NfNotFound); - }); - - it("should throw NfNotFound for an unknown wasm", () => { - expect(() => library.getAsset("unknown.wasm")).toThrow(NfNotFound); - }); - - it("should throw NfNotFound for an unknown wgsl", () => { - expect(() => library.getAsset("unknown.wgsl")).toThrow(NfNotFound); - }); - - it("should return undefined for an undefined path", () => { - expect(library.getAsset(undefined)).toBe(undefined); - expect(library.getAsset("")).toBe(undefined); - }); - }); -}); diff --git a/packages/config/.nvmrc b/packages/config/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/config/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md deleted file mode 100644 index f464d3a5..00000000 --- a/packages/config/CHANGELOG.md +++ /dev/null @@ -1,63 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -## Bug Fixes - -- Change url protocols validation on isIpOrURL validator in network (#398) ([541dd16](https://github.com/NanoForge-dev/Engine/commit/541dd16e307e355288ec49ec7ae75566bb7fe2b5)) by @Exeloo - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -## Bug Fixes - -- Change check for address from fqdn to url (#394) ([8823c59](https://github.com/NanoForge-dev/Engine/commit/8823c5911f8c5a673a96c32df9888b2dea4d6370)) by @Exeloo - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/config@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/config@1.1.0...@nanoforge-dev/config@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/config@1.1.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/config@1.0.1...@nanoforge-dev/config@1.1.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- Add loader given env to config registry (#246) ([dce12b7](https://github.com/NanoForge-dev/Engine/commit/dce12b7601b613e850987da1e0766634a821bdfc)) by @Exeloo - -# [@nanoforge-dev/config@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/config@1.0.0...@nanoforge-dev/config@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/config@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/config@1.0.0) - (2026-01-09) - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo -- Add a basic introduction readme ([b240964](https://github.com/NanoForge-dev/Engine/commit/b240964a265b31769a8c5422e23e20156ba56192)) by @MartinFillon -- Add building and dependency docs to every readme ([2d4785b](https://github.com/NanoForge-dev/Engine/commit/2d4785bdcb455e83337b37540f9ab6b3394c0850)) by @MartinFillon - -## Features - -- **packages/network:** Client and server for tcp/udp and networked pong as example (#156) ([839fb95](https://github.com/NanoForge-dev/Engine/commit/839fb95449f6ae0ee66d7f7e279374268b743f65)) by @Tchips46 -- **common, core, config:** Introduce configuration registry and validation system ([4fafb82](https://github.com/NanoForge-dev/Engine/commit/4fafb82576fec6866fc281ad5b10321d2ac430df)) by @Exeloo -- **config:** Add initial configuration for libraries ([57d910d](https://github.com/NanoForge-dev/Engine/commit/57d910d100489a45ea597e777fe530f018a8313e)) by @Exeloo - -## Refactor - -- Migrate namespaces to `@nanoforge-dev` and update related imports ([c84c927](https://github.com/NanoForge-dev/Engine/commit/c84c927ead941d914e5a9fd752fd3a5ac969f981)) by @Exeloo - diff --git a/packages/config/README.md b/packages/config/README.md deleted file mode 100644 index 470d71de..00000000 --- a/packages/config/README.md +++ /dev/null @@ -1,155 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/config` is a wrapper of [class-validator][class-validator] and [class-transformer][class-transformer] to imports validation and transformation decorators. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/config -yarn add @nanoforge-dev/config -pnpm add @nanoforge-dev/config -bun add @nanoforge-dev/config -``` - -## Warning - -This library is of exclusive usage for other libraries. To put variables in the environment to allow libraries to use it through this config library, you must put it in `.env` file at the root of your project (or in your environment) : - -```dotenv -NANOFORGE_CLIENT_SERVER_TCP_PORT=4445 -NANOFORGE_CLIENT_SERVER_UDP_PORT=4444 -NANOFORGE_CLIENT_SERVER_ADDRESS=127.0.0.1 -``` - -You must prefix your variables according to this table : - -| Prefix | Availability | -| :------------------ | :----------------------- | -| `NANOFORGE_CLIENT_` | Available in client only | -| `NANOFORGE_SERVER_` | Available in server only | -| `NANOFORGE_` | Available in both apps | - -⚠️ Prefixs are removed in libs - -You can also put it in init options (every value must be string or undefined) : - -```ts -import { type IRunOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { NetworkLibrary } from "@nanoforge-dev/network"; - -export async function main(options: IRunOptions) { - const app = NanoforgeFactory.createClient(); - - const network = new NetworkLibrary(); - - app.useNetwork(network); - - await app.init({ - ...options, - env: { - ...options.env, - SERVER_TCP_PORT: "4445", - SERVER_UDP_PORT: "4444", - SERVER_ADDRESS: "127.0.0.1", - }, - }); - - await app.run(); -} -``` - -## Example usage - -Initialize the library in your main file. - -```ts -export class NetworkClientLibrary extends BaseNetworkLibrary { - get __name(): string { - return "NetworkClientLibrary"; - } - - public override async __init(context: InitContext): Promise { - const config = await context.config.registerConfig(ClientConfigNetwork); - - // Do something with config - } -} -``` - -Using this config - -```ts -import { - Default, - Expose, - IsByteLength, - IsIpOrURL, - IsOptional, - IsPort, -} from "@nanoforge-dev/config"; - -export class ClientConfigNetwork { - // This var must be a string port (ex: "4444") but can be undefined - @Expose() - @IsOptional() - @IsPort() - SERVER_TCP_PORT?: string; - - @Expose() - @IsOptional() - @IsPort() - SERVER_UDP_PORT?: string; - - // This var must be ip address or fqdn (it cannot be undefined) - @Expose() - @IsIpOrURL() - SERVER_ADDRESS?: string; - - // This var must be a byte length between 2 and 64. It can be undefined as it as a default value. - @Expose() - @Default("PACKET_END") - @IsByteLength(2, 64) - MAGIC_VALUE!: string; -} -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/config -[npm]: https://www.npmjs.com/package/@nanoforge-dev/config -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md -[class-validator]: https://github.com/typestack/class-validator -[class-transformer]: https://github.com/typestack/class-transformer diff --git a/packages/config/package.json b/packages/config/package.json deleted file mode 100644 index 283e98b0..00000000 --- a/packages/config/package.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/config", - "version": "1.4.2", - "description": "NanoForge Engine - Config", - "keywords": [ - "nanoforge", - "game", - "engine" - ], - "homepage": "https://github.com/NanoForge-dev/Engine#readme", - "bugs": "https://github.com/NanoForge-dev/Engine/issues", - "license": "MIT", - "contributors": [ - "Bill ", - "Exelo ", - "Fexkoser ", - "Tchips " - ], - "files": [ - "dist" - ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", - "exports": { - ".": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "./package.json": "./package.json" - }, - "type": "module", - "directories": { - "lib": "src" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/config" - }, - "funding": "https://github.com/NanoForge-dev/Engine?sponsor", - "scripts": { - "build": "tsc --noEmit && tsdown --config-loader unrun", - "lint": "prettier --check . && eslint --format=pretty src", - "format": "prettier --write . && eslint --fix --format=pretty src", - "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/config/*'", - "release": "cliff-jumper", - "docs": "mint-tsdocs generate" - }, - "dependencies": { - "class-transformer": "catalog:config", - "class-validator": "catalog:config" - }, - "devDependencies": { - "@favware/cliff-jumper": "catalog:ci", - "@nanoforge-dev/utils-eslint-config": "workspace:*", - "@nanoforge-dev/utils-prettier-config": "workspace:*", - "@trivago/prettier-plugin-sort-imports": "catalog:lint", - "eslint": "catalog:lint", - "prettier": "catalog:lint", - "tsdown": "catalog:build", - "typescript": "catalog:core", - "unrun": "catalog:build" - }, - "packageManager": "pnpm@11.24.0", - "engines": { - "node": "26" - }, - "publishConfig": { - "access": "public" - }, - "lint-staged": { - "**": [ - "prettier --ignore-unknown --write" - ], - "src/**/*.ts": [ - "eslint --fix" - ] - } -} diff --git a/packages/config/src/default.ts b/packages/config/src/default.ts deleted file mode 100644 index ed2a78c3..00000000 --- a/packages/config/src/default.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Transform } from "class-transformer"; -import { type TransformFnParams } from "class-transformer/types/interfaces/metadata/transform-fn-params.interface"; - -/** - * Property decorator that supplies a fallback value when the environment - * variable is `undefined` or `null`. - * - * @remarks - * Pairs with `class-transformer`'s `@Expose` and `class-validator` decorators. - * The default is deep-cloned via `JSON.parse(JSON.stringify(…))` so objects - * are not shared between instances. - * - * @param defaultValue - The value to use when the property is absent. - * - * @example - * ```ts - * class MyConfig { - * \@Expose() - * \@Default("localhost") - * HOST!: string; - * } - * ``` - */ -export function Default(defaultValue: unknown): PropertyDecorator { - return Transform( - ({ value }: TransformFnParams) => value ?? JSON.parse(JSON.stringify(defaultValue)), - ); -} diff --git a/packages/config/src/exports/index.ts b/packages/config/src/exports/index.ts deleted file mode 100644 index 0b143852..00000000 --- a/packages/config/src/exports/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./class-transformer"; -export * from "./class-validator"; diff --git a/packages/config/src/index.ts b/packages/config/src/index.ts deleted file mode 100644 index eccc35fa..00000000 --- a/packages/config/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./exports"; -export * from "./default"; -export * from "./transformers"; -export * from "./validators"; diff --git a/packages/config/src/transformers/index.ts b/packages/config/src/transformers/index.ts deleted file mode 100644 index 77363e3a..00000000 --- a/packages/config/src/transformers/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TransformToBoolean } from "./boolean.transformer"; diff --git a/packages/config/src/validators/index.ts b/packages/config/src/validators/index.ts deleted file mode 100644 index 3887243a..00000000 --- a/packages/config/src/validators/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { IsIpOrURL } from "./is-ip-or-url.validator"; diff --git a/packages/core-editor/.nvmrc b/packages/core-editor/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/core-editor/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/core-editor/CHANGELOG.md b/packages/core-editor/CHANGELOG.md deleted file mode 100644 index 73068e2b..00000000 --- a/packages/core-editor/CHANGELOG.md +++ /dev/null @@ -1,57 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -## Bug Fixes - -- **core-editor:** Reload event searching for entities (#396) ([eb07c7f](https://github.com/NanoForge-dev/Engine/commit/eb07c7f2fa7ea834c40c7f78517ee7104c85c9b0)) by @Tchips46 - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Bug Fixes - -- **core-editor:** Run when don't paused (#377) ([09147d2](https://github.com/NanoForge-dev/Engine/commit/09147d2e71488c7028e1f5983f43d5ff724769ee)) by @Tchips46 - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -## Features - -- Add assets handling (#383) ([cda797a](https://github.com/NanoForge-dev/Engine/commit/cda797a793ee5074cd43503e55a8dd348a516305)) by @Exeloo -- Add drag and drop on graphics (#380) ([afffa7a](https://github.com/NanoForge-dev/Engine/commit/afffa7afd1f51eba2d2cd0d96fe47e5db04ac534)) by @Exeloo -- **core-editor:** Event listenner not runned if main loop is paused (#379) ([25053db](https://github.com/NanoForge-dev/Engine/commit/25053db388e277bc7e1181315f07249f121fcc94)) by @Tchips46 -- **graphic-2d:** Destroy konva js in the lib clear (#372) ([e1ae678](https://github.com/NanoForge-dev/Engine/commit/e1ae678e7420eb20a2152fc110550b786877e7a5)) by @Tchips46 -- **core-editor:** Implement events (#369) ([4ebf791](https://github.com/NanoForge-dev/Engine/commit/4ebf7911521b9114c9e8f4482bd59175fb35cf06)) by @Tchips46 - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/core-editor@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/core-editor@1.0.2...@nanoforge-dev/core-editor@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/core-editor@1.0.2](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/core-editor@1.0.1...@nanoforge-dev/core-editor@1.0.2) - (2026-04-29) - -## Bug Fixes - -- **render:** Change specific container canva for general html div (#323) ([6ea75f4](https://github.com/NanoForge-dev/Engine/commit/6ea75f4f3c1aa3d2f46bdbea1467f580cb9000bc)) by @Tchips46 - -# [@nanoforge-dev/core-editor@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/core-editor@1.0.0...@nanoforge-dev/core-editor@1.0.1) - (2026-04-21) - -## Bug Fixes - -- **core-editor:** Bind events listeners (#315) ([cb80b4c](https://github.com/NanoForge-dev/Engine/commit/cb80b4cd9a6649e793bb7fe1b52f05427eebc6d9)) by @Tchips46 - -# [@nanoforge-dev/core-editor@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/core-editor@1.0.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- **core-editor:** Hot reload entity component from save (#253) ([71e3699](https://github.com/NanoForge-dev/Engine/commit/71e36998d9f510a874a5c3022aa0cdfa6c6bdfac)) by @Tchips46 - diff --git a/packages/core-editor/README.md b/packages/core-editor/README.md deleted file mode 100644 index 89278938..00000000 --- a/packages/core-editor/README.md +++ /dev/null @@ -1,52 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/core-editor` is a package made to allow the editor to make change to a game even if it's already compiled and running. - -If you want a core to run your game use the `@nanoforge-dev/core`. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/core-editor -yarn add @nanoforge-dev/core-editor -pnpm add @nanoforge-dev/core-editor -bun add @nanoforge-dev/core-editor -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/core-editor -[npm]: https://www.npmjs.com/package/@nanoforge-dev/core-editor -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/core-editor/mint-tsdocs.config.json b/packages/core-editor/mint-tsdocs.config.json deleted file mode 100644 index 02fa5cc0..00000000 --- a/packages/core-editor/mint-tsdocs.config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/core-editor", - "lint": { - "eslint": { - "enabled": true - } - }, - "templates": { - "userTemplateDir": "../../docs/templates" - } -} diff --git a/packages/core-editor/package.json b/packages/core-editor/package.json deleted file mode 100644 index b227b2f3..00000000 --- a/packages/core-editor/package.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/core-editor", - "version": "1.4.2", - "description": "NanoForge Engine - Core Editor", - "keywords": [ - "nanoforge", - "game", - "engine" - ], - "homepage": "https://github.com/NanoForge-dev/Engine#readme", - "bugs": "https://github.com/NanoForge-dev/Engine/issues", - "license": "MIT", - "contributors": [ - "Bill ", - "Exelo ", - "Fexkoser ", - "Tchips " - ], - "files": [ - "dist" - ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", - "exports": { - ".": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "./package.json": "./package.json" - }, - "type": "module", - "directories": { - "lib": "src" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/core-editor" - }, - "funding": "https://github.com/NanoForge-dev/Engine?sponsor", - "scripts": { - "build": "tsc --noEmit && tsdown --config-loader unrun", - "lint": "prettier --check . && eslint --format=pretty src", - "format": "prettier --write . && eslint --fix --format=pretty src", - "test:unit": "vitest run --config ../../vitest.config.ts", - "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/core-editor/*'", - "release": "cliff-jumper", - "docs": "mint-tsdocs generate" - }, - "dependencies": { - "@nanoforge-dev/asset-manager": "workspace:*", - "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/ecs-client": "workspace:*", - "@nanoforge-dev/input": "workspace:*", - "class-transformer": "catalog:config", - "class-validator": "catalog:config" - }, - "devDependencies": { - "@favware/cliff-jumper": "catalog:ci", - "@nanoforge-dev/utils-eslint-config": "workspace:*", - "@nanoforge-dev/utils-prettier-config": "workspace:*", - "@trivago/prettier-plugin-sort-imports": "catalog:lint", - "eslint": "catalog:lint", - "prettier": "catalog:lint", - "tsdown": "catalog:build", - "typescript": "catalog:core", - "unrun": "catalog:build", - "vitest": "catalog:test" - }, - "packageManager": "pnpm@11.24.0", - "engines": { - "node": "26" - }, - "publishConfig": { - "access": "public" - }, - "lint-staged": { - "**": [ - "prettier --ignore-unknown --write" - ], - "src/**/*.ts": [ - "eslint --fix" - ] - } -} diff --git a/packages/core-editor/src/application/nanoforge-application.ts b/packages/core-editor/src/application/nanoforge-application.ts deleted file mode 100644 index c015675f..00000000 --- a/packages/core-editor/src/application/nanoforge-application.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { - type IAssetManagerLibrary, - type IComponentSystemLibrary, - type ILibrary, - type INetworkLibrary, - type IRunOptions, - NfNotInitializedException, -} from "@nanoforge-dev/common"; - -import { ApplicationConfig } from "../../../core/src/application/application-config"; -import type { IApplicationOptions } from "../../../core/src/application/application-options.type"; -import { EditableApplicationContext } from "../../../core/src/common/context/contexts/application.editable-context"; -import { Core } from "../core/core"; - -/** - * Base class for editor-mode NanoForge applications. - * - * @remarks - * Mirror of `NanoforgeApplication` from `@nanoforge-dev/core` with an - * extended `init` signature that accepts `IEditorRunOptions`. Use - * `NanoforgeFactory` from this package to create instances. - */ -export abstract class NanoforgeApplication { - protected applicationConfig: ApplicationConfig; - private _core?: Core; - private readonly _options: IApplicationOptions; - - /** - * @param options - Optional application-level settings such as tickRate. - */ - constructor(options?: Partial) { - this.applicationConfig = new ApplicationConfig(); - - this._options = { - tickRate: 60, - ...(options ?? {}), - }; - } - - /** - * Register a library under a custom symbol. - * - * @param sym - Unique symbol identifying the library slot. - * @param library - Library instance to register. - */ - public use(sym: symbol, library: ILibrary): void { - this.applicationConfig.useLibrary(sym, library); - } - - /** - * Register the component-system (ECS) library. - * - * @param library - ECS library instance. - */ - public useComponentSystem(library: IComponentSystemLibrary) { - this.applicationConfig.useComponentSystemLibrary(library); - } - - /** - * Register the network library. - * - * @param library - Network library instance. - */ - public useNetwork(library: INetworkLibrary) { - this.applicationConfig.useNetworkLibrary(library); - } - - /** - * Register the asset-manager library. - * - * @param library - Asset manager instance. - */ - public useAssetManager(library: IAssetManagerLibrary) { - this.applicationConfig.useAssetManagerLibrary(library); - } - - /** - * Initialise all registered libraries and prepare the engine for the game loop. - * - * @param options - Editor run options including save/events callbacks and canvas container. - */ - public init(options: IRunOptions): Promise { - this._core = new Core( - this.applicationConfig, - new EditableApplicationContext(this.applicationConfig.libraryManager), - ); - return this._core.init(options, this._options); - } - - /** - * Start the game loop. - * - * @throws `NfNotInitializedException` When called before `init`. - */ - public run() { - if (!this._core) throw new NfNotInitializedException("Core"); - return this._core?.run(); - } -} diff --git a/packages/core-editor/src/application/nanoforge-client.ts b/packages/core-editor/src/application/nanoforge-client.ts deleted file mode 100644 index 8f799fde..00000000 --- a/packages/core-editor/src/application/nanoforge-client.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - type IGraphicsLibrary, - type IInputLibrary, - type ISoundLibrary, -} from "@nanoforge-dev/common"; - -import { NanoforgeApplication } from "./nanoforge-application"; - -/** - * Client-side NanoForge application for editor mode. - * - * @remarks - * Extends `NanoforgeApplication` with graphics, input, and sound library - * slots. Create via the `core-editor` `NanoforgeFactory`. - */ -export class NanoforgeClient extends NanoforgeApplication { - /** - * Register the graphics library. - * - * @param library - Graphics library instance (e.g. Graphics2DLibrary). - */ - public useGraphics(library: IGraphicsLibrary) { - this.applicationConfig.useGraphicsLibrary(library); - } - - /** - * Register the input library. - * - * @param library - Input library instance (e.g. InputLibrary). - */ - public useInput(library: IInputLibrary) { - this.applicationConfig.useInputLibrary(library); - } - - /** - * Register the sound-effect library. - * - * @param library - Sound library instance (e.g. SoundLibrary). - */ - public useSound(library: ISoundLibrary) { - this.applicationConfig.useSoundLibrary(library); - } -} diff --git a/packages/core-editor/src/application/nanoforge-factory.ts b/packages/core-editor/src/application/nanoforge-factory.ts deleted file mode 100644 index b0599cbf..00000000 --- a/packages/core-editor/src/application/nanoforge-factory.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { type IApplicationOptions } from "../../../core/src/application/application-options.type"; -import { NanoforgeClient } from "./nanoforge-client"; -import { NanoforgeServer } from "./nanoforge-server"; - -class NanoforgeFactoryStatic { - /** - * Create a new editor-mode client application. - * - * @param options - Optional application settings (e.g. tickRate). - * @returns A pre-configured `NanoforgeClient` instance. - */ - createClient(options?: Partial): NanoforgeClient { - return new NanoforgeClient(options); - } - - /** - * Create a new editor-mode server application. - * - * @param options - Optional application settings (e.g. tickRate). - * @returns A pre-configured `NanoforgeServer` instance. - */ - createServer(options?: Partial): NanoforgeServer { - return new NanoforgeServer(options); - } -} - -/** - * Singleton factory for creating editor-mode NanoForge client and server - * applications. - * - * @remarks - * Use `NanoforgeFactory.createClient` or - * `NanoforgeFactory.createServer` to obtain an application instance that - * accepts `IEditorRunOptions` on `init`. - * - * @example - * ```ts - * import `NanoforgeFactory ` from "@nanoforge-dev/core-editor"; - * - * const client = NanoforgeFactory.createClient(); - * ``` - */ -export const NanoforgeFactory = new NanoforgeFactoryStatic(); diff --git a/packages/core-editor/src/application/nanoforge-server.ts b/packages/core-editor/src/application/nanoforge-server.ts deleted file mode 100644 index 5dfdb20d..00000000 --- a/packages/core-editor/src/application/nanoforge-server.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NanoforgeApplication } from "./nanoforge-application"; - -/** - * Server-side NanoForge application for editor mode. - * - * @remarks - * Extends `NanoforgeApplication` for use in server processes during - * editor sessions. Create via the `core-editor` `NanoforgeFactory`. - */ -export class NanoforgeServer extends NanoforgeApplication {} diff --git a/packages/core-editor/src/common/context/contexts/init.context.ts b/packages/core-editor/src/common/context/contexts/init.context.ts deleted file mode 100644 index 599e89aa..00000000 --- a/packages/core-editor/src/common/context/contexts/init.context.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { - type ApplicationContext, - type IConfigRegistry, - type IRunOptions, - InitContext, - type LibraryManager, -} from "@nanoforge-dev/common"; - -import { type EventEmitter } from "../event-emitter"; - -export class EditorInitContext extends InitContext { - private readonly _eventEmitter: EventEmitter; - - constructor( - context: ApplicationContext, - libraryManager: LibraryManager, - configRegistry: IConfigRegistry, - options: IRunOptions, - eventEmitter: EventEmitter, - ) { - super(context, libraryManager, configRegistry, options); - this._eventEmitter = eventEmitter; - } - - override get eventEmitter(): EventEmitter { - return this._eventEmitter; - } -} diff --git a/packages/core-editor/src/common/context/event-emitter.ts b/packages/core-editor/src/common/context/event-emitter.ts deleted file mode 100644 index ebd0d575..00000000 --- a/packages/core-editor/src/common/context/event-emitter.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { IRunOptions } from "@nanoforge-dev/common"; - -import type { IEventEmitter, ListenerType } from "./event-emitter.type"; -import type { CoreEvents, CoreEventsMap } from "./events/core-events"; -import type { EditorEvents, EditorEventsMap } from "./events/editor-events"; - -export class EventEmitter { - private coreEvents: IEventEmitter; - private editorEvents: IEventEmitter; - - constructor(opts: IRunOptions["editor"]) { - this.coreEvents = opts.coreEvents; - this.editorEvents = opts.editorEvents; - } - - runEvents(): void { - this.coreEvents.runEvents(); - } - - emit(event: K, ...args: EditorEventsMap[K]): void { - this.editorEvents.emitEvent(event, ...args); - } - - on( - event: K, - listener: ListenerType, - ): void { - this.coreEvents.on(event, listener); - } -} diff --git a/packages/core-editor/src/common/context/event-emitter.type.ts b/packages/core-editor/src/common/context/event-emitter.type.ts deleted file mode 100644 index 15cb504a..00000000 --- a/packages/core-editor/src/common/context/event-emitter.type.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** Callback signature for event listeners. */ -export type ListenerType< - Events extends string, - EventsMap extends Record, - K extends keyof EventsMap, -> = (...args: EventsMap[K]) => void; - -/** Signature of the waiting for execution events. */ -export type QueuedEvent = { - event: K; - args: EventsMap[K]; -}; - -/** - * Simple event emitter interface used for communication between the NanoForge - * editor and the running engine. - * - * @remarks - * Listeners are queued and processed via `runEvents` to keep the engine - * loop deterministic. - */ -export interface IEventEmitter> { - /** Map of event names to their registered listeners. */ - listeners: { - [K in keyof EventsMap]?: ListenerType[]; - }; - - /** Queue of events waiting to be dispatched by `runEvents`. */ - eventQueue: QueuedEvent[]; - - /** Drain the event queue and invoke all matching listeners. */ - runEvents(): void; - - /** - * Enqueue an event for dispatching on the next `runEvents` call. - * - * @param event - Event name or EventTypeEnum value. - * @param args - Optional arguments forwarded to listeners. - */ - emitEvent(event: K, ...args: EventsMap[K]): void; - - /** - * Register a listener for an event. Alias: `on`. - * - * @param event - Event name to subscribe to. - * @param listener - Callback invoked when the event fires. - */ - addListener( - event: K, - listener: ListenerType, - ): void; - /** Alias for `addListener`. */ - on(event: K, listener: ListenerType): void; - - /** - * Remove a previously registered listener. Alias: `off`. - * - * @param event - Event name to unsubscribe from. - * @param listener - The exact listener function to remove. - */ - removeListener( - event: K, - listener: ListenerType, - ): void; - /** Alias for `removeListener`. */ - off(event: K, listener: ListenerType): void; - - /** - * Remove all listeners registered for a specific event. - * - * @param event - Event name whose listeners should be cleared. - */ - removeListenersForEvent(event: keyof EventsMap): void; - /** Remove every registered listener across all events. */ - removeAllListeners(): void; -} diff --git a/packages/core-editor/src/common/context/events/core-events.ts b/packages/core-editor/src/common/context/events/core-events.ts deleted file mode 100644 index 03d041f0..00000000 --- a/packages/core-editor/src/common/context/events/core-events.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { type Save } from "../save.type"; - -/** - * Events that the NanoForge editor can emit to the running engine. - */ -export enum CoreEvents { - /** Reload only changed entity components params (live-patch) */ - HOT_RELOAD = "hot-reload", - /** Reload all entities component params */ - HARD_RELOAD = "hard-reload", - /** Don't execute the run function until UNPAUSE_GAME */ - PAUSE_GAME = "pause-game", - /** End main loop and clear */ - STOP_GAME = "stop-game", - /** resume executing the run function */ - UNPAUSE_GAME = "unpause-game", -} - -export interface CoreEventsMap { - [CoreEvents.HOT_RELOAD]: [save: Save]; - [CoreEvents.HARD_RELOAD]: [save: Save]; - [CoreEvents.PAUSE_GAME]: []; - [CoreEvents.STOP_GAME]: []; - [CoreEvents.UNPAUSE_GAME]: []; -} diff --git a/packages/core-editor/src/common/context/events/editor-events.ts b/packages/core-editor/src/common/context/events/editor-events.ts deleted file mode 100644 index d9b72fd6..00000000 --- a/packages/core-editor/src/common/context/events/editor-events.ts +++ /dev/null @@ -1,11 +0,0 @@ -export enum EditorEvents { - MOVE_COMPONENT = "move-component", -} - -export interface EditorEventsMap { - [EditorEvents.MOVE_COMPONENT]: [ - entityId: string, - componentId: string, - position: { x: number; y: number }, - ]; -} diff --git a/packages/core-editor/src/common/context/index.ts b/packages/core-editor/src/common/context/index.ts deleted file mode 100644 index 8b92a342..00000000 --- a/packages/core-editor/src/common/context/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { CoreEvents } from "./events/core-events"; -export { EditorEvents } from "./events/editor-events"; -export type { EventEmitter } from "./event-emitter"; diff --git a/packages/core-editor/src/common/context/options.type.ts b/packages/core-editor/src/common/context/options.type.ts deleted file mode 100644 index 5b121a5d..00000000 --- a/packages/core-editor/src/common/context/options.type.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { type IEventEmitter } from "./event-emitter.type"; -import { type CoreEvents, type CoreEventsMap } from "./events/core-events"; -import { type EditorEvents, type EditorEventsMap } from "./events/editor-events"; -import { type Save } from "./save.type"; - -/** - * Union of client and server editor run options accepted by - * `NanoforgeApplication.init` in editor mode. - * - * @deprecated Use `IRunOptions` instead. - */ -export type IEditorRunOptions = IEditorRunClientOptions | IEditorRunServerOptions; - -/** - * Run options for a client-side editor application. - * - * @deprecated Use `IRunClientOptions` instead. - * @remarks - * Extends the base run options with editor-specific communication channels. - */ -export interface IEditorRunClientOptions { - /** DOM element that will host the game canvas. */ - container: HTMLDivElement; - /** Map of virtual file paths to their resolved URL strings. */ - files: Map; - /** Runtime environment variables available to all libraries. */ - env: Record; - /** Editor integration hooks. */ - editor: { - /** Serialised scene state loaded or saved by the editor. */ - save: Save; - /** Event emitter for core-to-editor communication. */ - coreEvents: IEventEmitter; - /** Event emitter for editor-to-core communication. */ - editorEvents: IEventEmitter; - }; -} - -/** - * Run options for a server-side editor application. - * - * @deprecated Use `IRunServerOptions` instead. - * @remarks - * Extends the base server run options with editor-specific communication channels. - */ -export interface IEditorRunServerOptions { - /** Map of virtual file paths to their resolved URL strings. */ - files: Map; - /** Runtime environment variables available to all libraries. */ - env: Record; - /** Editor integration hooks. */ - editor: { - /** Serialised scene state loaded or saved by the editor. */ - save: Save; - /** Event emitter for core-to-editor communication. */ - coreEvents: IEventEmitter; - /** Event emitter for editor-to-core communication. */ - editorEvents: IEventEmitter; - }; -} diff --git a/packages/core-editor/src/common/context/save.type.ts b/packages/core-editor/src/common/context/save.type.ts deleted file mode 100644 index d29f2987..00000000 --- a/packages/core-editor/src/common/context/save.type.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Identifies the role a library plays in a saved scene. - */ -export enum SaveLibraryTypeEnum { - COMPONENT_SYSTEM = "component-system", - GRAPHICS = "graphics", - ASSET_MANAGER = "asset-manager", - NETWORK = "network", - INPUT = "input", - SOUND = "sound", -} - -/** - * Serialised representation of a registered library in a saved scene. - */ -export interface SaveLibrary { - /** Unique identifier for this library instance in the scene. */ - id: string; - /** Library role (one of `SaveLibraryTypeEnum` or a custom string). */ - type: SaveLibraryTypeEnum | string; - /** Human-readable name of the library. */ - name: string; - /** Module path used to import the library at runtime. */ - path: string; -} - -/** - * Serialised representation of an ECS component type in a saved scene. - */ -export interface SaveComponent { - /** Component class name. */ - name: string; - /** Module path used to import the component at runtime. */ - path: string; - /** Names of the constructor parameters exposed in the editor. */ - paramsNames: string[]; -} - -/** - * Serialised representation of an ECS system in a saved scene. - */ -export interface SaveSystem { - /** System class name. */ - name: string; - /** Module path used to import the system at runtime. */ - path: string; -} - -/** - * Serialised representation of an entity and its component data. - */ -export interface SaveEntity { - /** Unique identifier for this entity instance. */ - id: string; - /** Map of component name to its property values. */ - components: Record>; -} - -/** - * Root serialized scene state exchanged between the editor and the engine. - */ -export interface Save { - /** All libraries registered in the scene. */ - libraries: SaveLibrary[]; - /** All component types available in the scene. */ - components: SaveComponent[]; - /** All systems active in the scene. */ - systems: SaveSystem[]; - /** All spawned entities and their component data. */ - entities: SaveEntity[]; -} diff --git a/packages/core-editor/src/core/core.ts b/packages/core-editor/src/core/core.ts deleted file mode 100644 index cbaddad7..00000000 --- a/packages/core-editor/src/core/core.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { - ClearContext, - ClientLibraryManager, - Context, - type IRunnerLibrary, - type InitContext, - type LibraryHandle, - LibraryStatusEnum, - NfNotInitializedException, -} from "@nanoforge-dev/common"; -import { type IRunOptions } from "@nanoforge-dev/common"; - -import { type ApplicationConfig } from "../../../core/src/application/application-config"; -import type { IApplicationOptions } from "../../../core/src/application/application-options.type"; -import { type EditableApplicationContext } from "../../../core/src/common/context/contexts/application.editable-context"; -import { EditableExecutionContext } from "../../../core/src/common/context/contexts/executions/execution.editable-context"; -import { type EditableLibraryContext } from "../../../core/src/common/context/contexts/library.editable-context"; -import { ConfigRegistry } from "../../../core/src/config/config-registry"; -import { EditorInitContext } from "../common/context/contexts/init.context"; -import { CoreEditor } from "../editor/core-editor"; - -export class Core { - private readonly config: ApplicationConfig; - private readonly context: EditableApplicationContext; - private options?: IApplicationOptions; - public editor?: CoreEditor; - private _configRegistry?: ConfigRegistry; - - constructor(config: ApplicationConfig, context: EditableApplicationContext) { - this.config = config; - this.context = context; - } - - public async init(options: IRunOptions, appOptions: IApplicationOptions): Promise { - this.options = appOptions; - this._configRegistry = new ConfigRegistry(options.env); - this.editor = new CoreEditor(this, options.editor, this.config); - await this.runInit(this.getInitContext(options)); - } - - public async run(): Promise { - if (!this.options) throw new NfNotInitializedException("Core Editor"); - - const context = this.getExecutionContext(); - const clientContext = this.getClientContext(); - const libraries = this.config.libraryManager.getExecutionLibraries(); - - const runner = async (delta: number) => { - this.context.setDelta(delta); - await this.runExecute(clientContext, libraries); - }; - - const tickLengthMs = 1000 / this.options.tickRate; - let previousTick = Date.now(); - - const render = async () => { - if (!context.application.isRunning) { - await this.runClear(this.getClearContext()); - return; - } - const tickStart = Date.now(); - this.editor?.runEvents(); - if (!this.editor?.isPaused) await runner(tickStart - previousTick); - previousTick = tickStart; - setTimeout(render, tickLengthMs + tickStart - Date.now()); - }; - - context.application.setIsRunning(true); - setTimeout(render); - } - - public getExecutionContext(): EditableExecutionContext { - return new EditableExecutionContext(this.context, this.config.libraryManager); - } - - private getInitContext(options: IRunOptions): InitContext { - if (!this._configRegistry || !this.editor) throw new NfNotInitializedException("Core Editor"); - - return new EditorInitContext( - this.context, - this.config.libraryManager, - this._configRegistry, - options, - this.editor.eventEmitter, - ); - } - - private getClearContext(): ClearContext { - return new ClearContext(this.context, this.config.libraryManager); - } - - private getClientContext(): Context { - return new Context(this.context, new ClientLibraryManager(this.config.libraryManager)); - } - - private async runInit(context: InitContext): Promise { - for (const handle of this.config.libraryManager.getInitLibraries()) { - await handle.library.__init(context); - (handle.context as EditableLibraryContext).setStatus(LibraryStatusEnum.LOADED); - } - } - - private async runExecute(context: Context, libraries: LibraryHandle[]) { - for (const handle of libraries) { - await handle.library.__run(context); - } - } - - private async runClear(context: ClearContext) { - for (const handle of this.config.libraryManager.getClearLibraries()) { - await handle.library.__clear(context); - (handle.context as EditableLibraryContext).setStatus(LibraryStatusEnum.CLEAR); - } - } -} diff --git a/packages/core-editor/src/editor/core-editor.ts b/packages/core-editor/src/editor/core-editor.ts deleted file mode 100644 index b15f3a59..00000000 --- a/packages/core-editor/src/editor/core-editor.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { type IAssetManagerLibrary, type IRunOptions, NfNotFound } from "@nanoforge-dev/common"; -import type { ECSClientLibrary, Entity } from "@nanoforge-dev/ecs-client"; - -import type { ApplicationConfig } from "../../../core/src/application/application-config"; -import { EventEmitter } from "../common/context/event-emitter"; -import { CoreEvents } from "../common/context/events/core-events"; -import type { Save } from "../common/context/save.type"; -import type { Core } from "../core/core"; - -export class CoreEditor { - public eventEmitter: EventEmitter; - private ecsLibrary: ECSClientLibrary; - private assetLibrary: IAssetManagerLibrary; - private lastLoadedSave: Save; - private core: Core; - private _isPaused: boolean = false; - - constructor(core: Core, editor: IRunOptions["editor"], config: ApplicationConfig) { - this.eventEmitter = new EventEmitter(editor); - this.lastLoadedSave = JSON.parse(JSON.stringify(editor.save)); - - this.ecsLibrary = config.getComponentSystemLibrary().library; - this.assetLibrary = config.getAssetManagerLibrary().library; - - this.eventEmitter.on(CoreEvents.HOT_RELOAD, this.hotReloadEvent.bind(this)); - this.eventEmitter.on(CoreEvents.HARD_RELOAD, this.hardReloadEvent.bind(this)); - this.eventEmitter.on(CoreEvents.PAUSE_GAME, this.pauseGameEvent.bind(this)); - this.eventEmitter.on(CoreEvents.STOP_GAME, this.stopGameEvent.bind(this)); - this.eventEmitter.on(CoreEvents.UNPAUSE_GAME, this.unpauseGameEvent.bind(this)); - - this.core = core; - } - - get isPaused(): boolean { - return this._isPaused; - } - - public runEvents() { - this.eventEmitter.runEvents(); - } - - public hotReloadEvent(save: Save): void { - this.reloadEvent(save, false); - } - - public hardReloadEvent(save: Save): void { - this.reloadEvent(save, true); - } - - public pauseGameEvent(): void { - this._isPaused = true; - } - public unpauseGameEvent(): void { - this._isPaused = false; - } - - public stopGameEvent(): void { - this.core.getExecutionContext().application.setIsRunning(false); - } - - private reloadEvent(save: Save, hard: boolean): void { - const reg = this.ecsLibrary.registry; - save.entities.forEach(({ id, components }) => { - Object.entries(components).forEach(([componentName, params]) => { - const ogComponent = save.components.find(({ name }) => name === componentName); - if (!ogComponent) { - throw new NfNotFound("Component: " + componentName + " not found in saved components"); - } - const ecsEntity: Entity = this.getEntityFromEntityId(id); - const ecsComponent = reg.getEntityComponent(ecsEntity, { - name: componentName, - }); - Object.entries(params).forEach(([paramName, paramValue]) => { - if (!hard) { - const lastLoadedParam = this.lastLoadedSave.entities.find((e) => e.id === id) - ?.components[componentName]?.[paramName]; - if (lastLoadedParam === paramValue) return; - } - - const ogParam = ogComponent.paramsNames.find( - (param) => param === paramName || param === `__RESERVED_ASSET_${paramName}`, - ); - if (!ogParam) return; - - ecsComponent[paramName] = ogParam.startsWith("__RESERVED_ASSET_") - ? this.assetLibrary.getAsset(paramValue) - : paramValue; - }); - reg.addComponent(ecsEntity, ecsComponent); - }); - }); - this.lastLoadedSave = JSON.parse(JSON.stringify(save)); - } - - private getEntityFromEntityId(entityId: string): Entity { - const reg = this.ecsLibrary.registry; - return reg.entityFromIndex( - reg - .getIndexedZipper([{ name: `__RESERVED_entityId` }]) - .find(({ __RESERVED_entityId }) => __RESERVED_entityId.entityId === entityId).id, - ); - } -} diff --git a/packages/core-editor/src/index.ts b/packages/core-editor/src/index.ts deleted file mode 100644 index b6bd2792..00000000 --- a/packages/core-editor/src/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { EventEmitter } from "./common/context/event-emitter"; -import type { IEventEmitter } from "./common/context/event-emitter.type"; -import type { CoreEvents, CoreEventsMap } from "./common/context/events/core-events"; -import type { EditorEvents, EditorEventsMap } from "./common/context/events/editor-events"; -import type { Save } from "./common/context/save.type"; - -declare module "@nanoforge-dev/common" { - interface IRunClientOptions { - /** Editor integration hooks. */ - editor: { - /** Serialised scene state loaded or saved by the editor. */ - save: Save; - /** Event emitter for core-to-editor communication. */ - coreEvents: IEventEmitter; - /** Event emitter for editor-to-core communication. */ - editorEvents: IEventEmitter; - }; - } - - interface IRunServerOptions { - /** Editor integration hooks. */ - editor: { - /** Serialised scene state loaded or saved by the editor. */ - save: Save; - /** Event emitter for core-to-editor communication. */ - coreEvents: IEventEmitter; - /** Event emitter for editor-to-core communication. */ - editorEvents: IEventEmitter; - }; - } - - interface InitContext { - eventEmitter: EventEmitter; - } -} - -export * from "./application/nanoforge-factory"; - -export type { NanoforgeClient } from "./application/nanoforge-client"; -export type { NanoforgeServer } from "./application/nanoforge-server"; -export { type EventEmitter, CoreEvents, EditorEvents } from "./common/context"; diff --git a/packages/core-editor/test/editor-feature.spec.ts b/packages/core-editor/test/editor-feature.spec.ts deleted file mode 100644 index c63fc5d1..00000000 --- a/packages/core-editor/test/editor-feature.spec.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { type IRunOptions } from "@nanoforge-dev/common"; -import { afterEach, describe, expect, it, vi } from "vitest"; - -import { type ApplicationConfig } from "../../core/src/application/application-config"; -import { CoreEvents } from "../src"; -import { type Save, type SaveComponent, type SaveEntity } from "../src/common/context/save.type"; -import { type Core } from "../src/core/core"; -import { CoreEditor } from "../src/editor/core-editor"; -import { EventEmitter } from "./helpers/event-emitter"; - -describe("EditorFeatures", () => { - afterEach(() => { - vi.restoreAllMocks(); - }); - - describe("eventEmitter", () => { - it("should execute eventQueue once", async () => { - const events = new EventEmitter(); - events.emitEvent(CoreEvents.HOT_RELOAD); - events.emitEvent(CoreEvents.HOT_RELOAD); - const spyHotReload = vi - .spyOn(CoreEditor.prototype, "hotReloadEvent") - .mockImplementation(() => {}); - new CoreEditor( - {} as unknown as Core, - { coreEvents: events, save: { libraries: [] } } as unknown as IRunOptions["editor"], - { - getAssetManagerLibrary: () => ({ library: {} }), - getComponentSystemLibrary: () => ({ library: {} }), - } as ApplicationConfig, - ).runEvents(); - expect(spyHotReload).toHaveBeenCalledTimes(2); - }); - }); - - describe("askEntitiesHotReload", () => { - it("should reload entities with new save variables", async () => { - const FakeRegistry = vi.fn( - class { - addComponent = vi.fn(); - getIndexedZipper = vi.fn(() => [ - { - id: 2, - __RESERVED_entityId: { - entityId: "ent2", - name: "__RESERVED_entityId", - }, - }, - { - id: 3, - __RESERVED_entityId: { - entityId: "ent3", - name: "__RESERVED_entityId", - }, - }, - ]); - getEntityComponent = vi.fn((entity: number, component) => { - return ( - { - 2: { - Position: { - name: "Position", - x: 3, - y: 4, - }, - Bullets: { - name: "Bullets", - number: 4, - bulletTypes: ["9mm"], - }, - __RESERVED_entityId: { - entityId: "ent2", - }, - }, - 3: { - Position: { - name: "Position", - x: 7, - y: 8, - }, - __RESERVED_entityId: { - entityId: "ent3", - }, - }, - } as Record> - )[entity]?.[component.name]; - }); - entityFromIndex = vi.fn((index) => { - return index; - }); - }, - ); - - const components: SaveComponent[] = [ - { - name: "Position", - path: "/tmp/pos", - paramsNames: ["x", "y"], - }, - { - name: "Bullets", - path: "/tmp/pos", - paramsNames: ["bulletTypes", "number"], - }, - ]; - const entities: SaveEntity[] = [ - { - id: "ent2", - components: { - Position: { - x: 1, - y: 2, - }, - Bullets: { - bulletTypes: ["fire", "water", "rocket"], - number: 1000, - }, - }, - }, - { - id: "ent3", - components: { - Position: { - x: 5, - y: 6, - }, - }, - }, - ]; - const fakeReg = new FakeRegistry(); - const events = new EventEmitter(); - new CoreEditor( - {} as unknown as Core, - { - save: { - components, - entities, - } as any as Save, - coreEvents: events, - } as any as IRunOptions["editor"], - { - getAssetManagerLibrary: () => ({ - library: { getAsset: vi.fn((name: string) => ({ path: name })) }, - }), - getComponentSystemLibrary: () => ({ library: { registry: fakeReg } }), - } as unknown as ApplicationConfig, - ).hotReloadEvent({ components, entities } as any as Save); - expect(fakeReg.getIndexedZipper).toHaveBeenCalledWith([{ name: "__RESERVED_entityId" }]); - expect(fakeReg.getEntityComponent).toHaveBeenNthCalledWith(1, 2, { name: "Position" }); - expect(fakeReg.getEntityComponent).toHaveBeenNthCalledWith(2, 2, { name: "Bullets" }); - expect(fakeReg.getEntityComponent).toHaveBeenNthCalledWith(3, 3, { name: "Position" }); - expect(fakeReg.addComponent).toHaveBeenNthCalledWith(1, 2, { name: "Position", x: 3, y: 4 }); - expect(fakeReg.addComponent).toHaveBeenNthCalledWith(2, 2, { - name: "Bullets", - bulletTypes: ["fire", "water", "rocket"], - number: 4, - }); - expect(fakeReg.addComponent).toHaveBeenNthCalledWith(3, 3, { name: "Position", x: 7, y: 8 }); - }); - }); -}); diff --git a/packages/core-editor/test/helpers/event-emitter.ts b/packages/core-editor/test/helpers/event-emitter.ts deleted file mode 100644 index a06695f2..00000000 --- a/packages/core-editor/test/helpers/event-emitter.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { - type IEventEmitter, - type ListenerType, - type QueuedEvent, -} from "../../src/common/context/event-emitter.type"; - -export class EventEmitter< - Events extends string, - EventsMap extends Record, -> implements IEventEmitter { - public listeners: { - [K in keyof EventsMap]?: ListenerType[]; - } = {}; - - public eventQueue: QueuedEvent[] = []; - private readonly _dequeueOnEmit: boolean; - - constructor(dequeueOnEmit = false) { - this._dequeueOnEmit = dequeueOnEmit; - } - - runEvents(): void { - this.eventQueue.forEach((e) => { - this._executeEvent(e); - }); - - this.eventQueue = []; - } - - emitEvent(event: K, ...args: EventsMap[K]): void { - this.eventQueue.push({ - event, - args, - }); - if (this._dequeueOnEmit) this.runEvents(); - } - addListener( - event: K, - listener: ListenerType, - ): void { - if (!this.listeners[event]) this.listeners[event] = []; - this.listeners[event].push(listener); - } - on(event: K, listener: ListenerType): void { - this.addListener(event, listener); - } - - removeListener( - event: K, - listener: ListenerType, - ): void { - if (!this.listeners[event]) return; - const index = this.listeners[event].indexOf(listener); - if (index >= 0) { - this.listeners[event].splice(index, 1); - } - } - off(event: K, listener: ListenerType): void { - this.removeListener(event, listener); - } - - removeListenersForEvent(event: keyof EventsMap): void { - if (!this.listeners[event]) return; - this.listeners[event] = []; - } - removeAllListeners(): void { - this.listeners = {}; - } - - private _executeEvent({ - event, - args, - }: QueuedEvent): void { - this.listeners[event]?.forEach((listener) => { - try { - listener(...args); - } catch (error) { - console.error(`Error handling event [${String(event)}]:`, error); - } - }); - } -} diff --git a/packages/ecs-client/.gitignore b/packages/ecs-client/.gitignore deleted file mode 100644 index ec337acd..00000000 --- a/packages/ecs-client/.gitignore +++ /dev/null @@ -1,276 +0,0 @@ -### 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 -!build/ - -# CMakeg -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 - -# Turbo -.turbo/ - -# Compiled files -src/**/*.js -src/**/*.d.ts - -# pubilc directory -lib/ -compile_commands.json -emsdk/ - -# mint-tsdocs cache -docs/.tsdocs/ diff --git a/packages/ecs-client/.nvmrc b/packages/ecs-client/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/ecs-client/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/ecs-client/.prettierignore b/packages/ecs-client/.prettierignore deleted file mode 100644 index 711c4e5a..00000000 --- a/packages/ecs-client/.prettierignore +++ /dev/null @@ -1,13 +0,0 @@ -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock -bun.lock - -.turbo/ -node_modules/ -dist/ -coverage/ -CHANGELOG.md - -lib/ diff --git a/packages/ecs-client/CHANGELOG.md b/packages/ecs-client/CHANGELOG.md deleted file mode 100644 index 1382e9a4..00000000 --- a/packages/ecs-client/CHANGELOG.md +++ /dev/null @@ -1,75 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/ecs-client@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.1.4...@nanoforge-dev/ecs-client@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/ecs-client@1.1.4](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.1.3...@nanoforge-dev/ecs-client@1.1.4) - (2026-04-29) - -## Bug Fixes - -- **render:** Change specific container canva for general html div (#323) ([6ea75f4](https://github.com/NanoForge-dev/Engine/commit/6ea75f4f3c1aa3d2f46bdbea1467f580cb9000bc)) by @Tchips46 - -# [@nanoforge-dev/ecs-client@1.1.3](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.1.2...@nanoforge-dev/ecs-client@1.1.3) - (2026-04-19) - -# [@nanoforge-dev/ecs-client@1.1.2](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.1.1...@nanoforge-dev/ecs-client@1.1.2) - (2026-04-15) - -## Bug Fixes - -- Rollback and remove assets dir in tsup config (#301) ([46df4b9](https://github.com/NanoForge-dev/Engine/commit/46df4b9bb88df445d300fa1bebe65548f1a6231e)) by @Exeloo - -# [@nanoforge-dev/ecs-client@1.1.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.1.0...@nanoforge-dev/ecs-client@1.1.1) - (2026-04-15) - -## Bug Fixes - -- Change assets dir to fix wasm import (#298) ([eb33c16](https://github.com/NanoForge-dev/Engine/commit/eb33c166f9ba51a24e97e37b4c43fd14fd61291d)) by @Exeloo - -# [@nanoforge-dev/ecs-client@1.1.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.0.1...@nanoforge-dev/ecs-client@1.1.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- **core-editor:** Hot reload entity component from save (#253) ([71e3699](https://github.com/NanoForge-dev/Engine/commit/71e36998d9f510a874a5c3022aa0cdfa6c6bdfac)) by @Tchips46 - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/ecs-client@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-client@1.0.0...@nanoforge-dev/ecs-client@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/ecs-client@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/ecs-client@1.0.0) - (2026-01-09) - -## Bug Fixes - -- **ecs:** Change ecs tests build (#152) ([246759e](https://github.com/NanoForge-dev/Engine/commit/246759ead7bee2364f8405fab50133463ae88978)) by @Exeloo - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo - -## Features - -- Split ecs between client and server (#142) ([18fdd4a](https://github.com/NanoForge-dev/Engine/commit/18fdd4ab8d693ddcd0d3290e9ade127c4f410009)) by @Exeloo - diff --git a/packages/ecs-client/Makefile b/packages/ecs-client/Makefile deleted file mode 100644 index 26362cfb..00000000 --- a/packages/ecs-client/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -BASE_DIR = node_modules/@nanoforge-dev/ecs-lib - -SRC = $(BASE_DIR)/wasm/SparseArray.cpp\ - $(BASE_DIR)/wasm/Entity.cpp\ - $(BASE_DIR)/wasm/Utils.cpp\ - $(BASE_DIR)/wasm/Registry.cpp - -NAME := libecs - -OUT_DIR = lib -JS_NAME = $(OUT_DIR)/$(NAME).js -WASM_NAME = $(OUT_DIR)/$(NAME).wasm -TS_NAME = $(OUT_DIR)/$(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_NAME) $(WASM_NAME) - -$(TS_NAME) $(JS_NAME) $(WASM_NAME): LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s ENVIRONMENT=web -$(TS_NAME) $(JS_NAME) $(WASM_NAME) &: $(OBJ) - @mkdir -p $(OUT_DIR) - $(CC) $(OBJ) $(LDFLAGS) -o $(JS_NAME) - cp $(BASE_DIR)/$(TS_NAME) $(TS_NAME) - -clean: - $(RM) $(OBJ) - $(RM) $(JS_NAME) $(WASM_NAME) $(TS_NAME) - -fclean: clean - -tests: LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -tests: $(OBJ) - @mkdir -p $(OUT_DIR) - $(CC) $(OBJ) $(LDFLAGS) -o $(JS_NAME) - cp $(BASE_DIR)/$(TS_NAME) $(TS_NAME) - -re: fclean all - -.PHONY: re fclean all clean tests diff --git a/packages/ecs-client/README.md b/packages/ecs-client/README.md deleted file mode 100644 index 08a05abb..00000000 --- a/packages/ecs-client/README.md +++ /dev/null @@ -1,125 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/ecs-client` is a wrapper of `@nanoforge-dev/ecs-lib` for client-side usage. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/ecs-client -yarn add @nanoforge-dev/ecs-client -pnpm add @nanoforge-dev/ecs-client -bun add @nanoforge-dev/ecs-client -``` - -## Example usage - -Initialize the library in your main file. - -```ts -import { type IRunOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSClientLibrary } from "@nanoforge-dev/ecs-client"; - -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const ecs = new ECSClientLibrary(); - - app.useComponentSystem(ecs); - - await app.init(options); - - const registry = ecs.registry; - - const entity = registry.spawnEntity(); - registry.addComponent(entity, new ExampleComponent("foo", 42)); - - registry.addSystem(exampleSystem); - - await app.run(); -} -``` - -With component - -```ts -export class ExampleComponent { - name = this.constructor.name; - - constructor( - public paramA: string, - public paramB: number, - public paramC: boolean = false, - ) {} - - get foo() { - return "bar"; - } - - get paramAOrDefault() { - return this.paramC ? this.paramA : "default"; - } - - addOne() { - this.paramB += 1; - } -} -``` - -And system - -```ts -export const exampleSystem = (registry: Registry, ctx: Context) => { - const entities = registry.getZipper([ExampleComponent]); - - entities.forEach((entity) => { - if (entity.ExampleComponent.paramA === "end") { - ctx.app.setIsRunning(false); - return; - } - - if (entity.ExampleComponent.paramB === 0) entity.ExampleComponent.paramA = "end"; - - if (entity.ExampleComponent.paramB >= 0) - entity.ExampleComponent.paramB = entity.ExampleComponent.paramB - 1; - }); -}; -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/ecs-client -[npm]: https://www.npmjs.com/package/@nanoforge-dev/ecs-client -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/ecs-client/mint-tsdocs.config.json b/packages/ecs-client/mint-tsdocs.config.json deleted file mode 100644 index 142757d9..00000000 --- a/packages/ecs-client/mint-tsdocs.config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/ecs-client", - "lint": { - "eslint": { - "enabled": true - } - }, - "templates": { - "userTemplateDir": "../../docs/templates" - } -} diff --git a/packages/ecs-client/src/ecs-client-library.ts b/packages/ecs-client/src/ecs-client-library.ts deleted file mode 100644 index a5aaab4a..00000000 --- a/packages/ecs-client/src/ecs-client-library.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { type InitContext } from "@nanoforge-dev/common"; -import { AbstractECSLibrary } from "@nanoforge-dev/ecs-lib"; - -import { default as Module } from "../lib/libecs"; - -/** - * Client-side ECS library backed by the compiled WASM module. - * - * @remarks - * Loads `libecs.wasm` from the asset manager and initialises the entity - * registry. Register with the application: - * - * ```ts - * client.useComponentSystem(new ECSClientLibrary()); - * ``` - * - * Access the registry in game code: - * ```ts - * const ecs = ctx.libraries.getComponentSystem().library; - * const entity = ecs.registry.spawnEntity(); - * ``` - */ -export class ECSClientLibrary extends AbstractECSLibrary { - constructor() { - super(); - this.path = "libecs.wasm"; - } - - /** @internal */ - get __name(): string { - return "ECSLibrary"; - } - - /** @internal */ - override async __init(context: InitContext): Promise { - const wasmFile = context.libraries.getAssetManager().library.getAsset(this.path); - this.module = await Module({ locateFile: () => wasmFile.path }); - this._registry = new this.module.Registry(); - } -} diff --git a/packages/ecs-client/src/index.ts b/packages/ecs-client/src/index.ts deleted file mode 100644 index e87c457a..00000000 --- a/packages/ecs-client/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-ignore -import "../lib/libecs.wasm"; - -export type { - Component, - EditorComponentManifest, - EditorSystemManifest, - System, - Registry, - Entity, - SparseArray, -} from "@nanoforge-dev/ecs-lib"; - -export { ECSClientLibrary } from "./ecs-client-library"; diff --git a/packages/ecs-client/test/ecs-client-library.spec.ts b/packages/ecs-client/test/ecs-client-library.spec.ts deleted file mode 100644 index 6bf25106..00000000 --- a/packages/ecs-client/test/ecs-client-library.spec.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { ClearContext, type IConfigRegistry, InitContext } from "@nanoforge-dev/common"; -import { beforeAll, beforeEach, describe, expect, it } from "vitest"; - -import { EditableApplicationContext } from "../../core/src/common/context/contexts/application.editable-context"; -import { EditableLibraryManager } from "../../core/src/common/library/manager/library.manager"; -import { type Registry } from "../lib/libecs"; -import { ECSClientLibrary } from "../src/ecs-client-library"; - -class Position { - name: string = "Position"; - constructor( - public x: number, - public y: number, - ) {} -} - -class Velocity { - name: string = "Velocity"; - constructor( - public x: number, - public y: number, - ) {} -} - -const getRunSystemsParams = (registry: Registry) => ({ - libs: { getComponentSystem: () => ({ registry }) }, -}); - -const assetManager = new AssetManagerLibrary(); -const libraryManager = new EditableLibraryManager(); -const appContext = new EditableApplicationContext(libraryManager); -const configRegistry = {} as IConfigRegistry; -const initContext = new InitContext(appContext, libraryManager, configRegistry, { - // @ts-ignore - container: null, - files: new Map([["/libecs.wasm", "./lib/libecs.wasm"]]), -}); -const clearContext = new ClearContext(appContext, libraryManager); -libraryManager.setAssetManager(assetManager); - -describe("ECSClientLibrary", () => { - let ecs: ECSClientLibrary; - let registry: Registry; - - beforeAll(async () => { - await assetManager.__init(initContext); - }); - - beforeEach(async () => { - ecs = new ECSClientLibrary(); - await ecs.__init(initContext); - registry = ecs.registry; - }); - - describe("metadata", () => { - it("should expose the correct library name", () => { - expect(ecs.__name).toBe("ECSLibrary"); - }); - }); - - describe("entity management", () => { - it("should spawn an entity with id 0", () => { - const entity = registry.spawnEntity(); - expect(entity).toBeDefined(); - expect(entity.getId()).toBe(0); - }); - - it("should assign incrementing ids to spawned entities", () => { - const e0 = registry.spawnEntity(); - const e1 = registry.spawnEntity(); - const e2 = registry.spawnEntity(); - expect(e0.getId()).toBe(0); - expect(e1.getId()).toBe(1); - expect(e2.getId()).toBe(2); - }); - - it("should kill an entity and remove its components", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.killEntity(entity); - expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); - }); - - it("should kill an entity with multiple components", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.addComponent(entity, new Velocity(3, 4)); - registry.killEntity(entity); - expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); - expect(registry.getComponents(Velocity).get(entity.getId())).toBeUndefined(); - }); - }); - - describe("component management", () => { - it("should add a component to an entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( - new Position(1, 2), - ); - }); - - it("should override a component on an entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.addComponent(entity, new Position(9, 9)); - expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( - new Position(9, 9), - ); - }); - - it("should add multiple component types to the same entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(3, 4)); - registry.addComponent(entity, new Velocity(1, 0)); - expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( - new Position(3, 4), - ); - expect(registry.getComponents(Velocity).get(entity.getId())).toStrictEqual( - new Velocity(1, 0), - ); - }); - - it("should remove a component from an entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.removeComponent(entity, Position); - expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); - }); - - it("should track component count across multiple entities", () => { - const e0 = registry.spawnEntity(); - const e1 = registry.spawnEntity(); - registry.addComponent(e0, new Position(0, 0)); - registry.addComponent(e1, new Position(1, 1)); - expect(registry.getComponents(Position).size()).toBe(2); - }); - }); - - describe("system management", () => { - it("should run a registered system once per call", () => { - let counter = 0; - registry.addSystem(() => { - counter += 1; - }); - registry.runSystems(getRunSystemsParams(registry)); - expect(counter).toBe(1); - }); - - it("should run all registered systems in order", () => { - const order: number[] = []; - registry.addSystem(() => order.push(1)); - registry.addSystem(() => order.push(2)); - registry.runSystems(getRunSystemsParams(registry)); - expect(order).toStrictEqual([1, 2]); - }); - - it("should run systems multiple times across multiple calls", () => { - let counter = 0; - registry.addSystem(() => { - counter += 1; - }); - for (let i = 0; i < 5; i++) { - registry.runSystems(getRunSystemsParams(registry)); - } - expect(counter).toBe(5); - }); - }); - - describe("lifecycle", () => { - it("should clear without error", async () => { - await expect(ecs.__clear(clearContext)).resolves.not.toThrow(); - }); - }); -}); diff --git a/packages/ecs-lib/.gitignore b/packages/ecs-lib/.gitignore deleted file mode 100644 index 5aadf52a..00000000 --- a/packages/ecs-lib/.gitignore +++ /dev/null @@ -1,280 +0,0 @@ -### 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 -!build/ - -# CMakeg -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 - -# Turbo -.turbo/ - -# 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/ -docs/xml - -# mint-tsdocs cache -docs/.tsdocs/ diff --git a/packages/ecs-lib/.nvmrc b/packages/ecs-lib/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/ecs-lib/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/ecs-lib/.prettierignore b/packages/ecs-lib/.prettierignore deleted file mode 100644 index 8fa0eca3..00000000 --- a/packages/ecs-lib/.prettierignore +++ /dev/null @@ -1,14 +0,0 @@ -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock -bun.lock - -.turbo/ -node_modules/ -dist/ -coverage/ -CHANGELOG.md - -lib/libecs.d.ts -lib/libecs.js diff --git a/packages/ecs-lib/CHANGELOG.md b/packages/ecs-lib/CHANGELOG.md deleted file mode 100644 index 1b4d1b9a..00000000 --- a/packages/ecs-lib/CHANGELOG.md +++ /dev/null @@ -1,86 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -## Bug Fixes - -- **core-editor:** Reload event searching for entities (#396) ([eb07c7f](https://github.com/NanoForge-dev/Engine/commit/eb07c7f2fa7ea834c40c7f78517ee7104c85c9b0)) by @Tchips46 - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -## Features - -- Add assets handling (#383) ([cda797a](https://github.com/NanoForge-dev/Engine/commit/cda797a793ee5074cd43503e55a8dd348a516305)) by @Exeloo -- Add drag and drop on graphics (#380) ([afffa7a](https://github.com/NanoForge-dev/Engine/commit/afffa7afd1f51eba2d2cd0d96fe47e5db04ac534)) by @Exeloo -- **core-editor:** Event listenner not runned if main loop is paused (#379) ([25053db](https://github.com/NanoForge-dev/Engine/commit/25053db388e277bc7e1181315f07249f121fcc94)) by @Tchips46 -- Indexed zipper (#378) ([208b330](https://github.com/NanoForge-dev/Engine/commit/208b330bfd358561fca259b03bebc50563022d35)) by @Tchips46 -- **core-editor:** Implement events (#369) ([4ebf791](https://github.com/NanoForge-dev/Engine/commit/4ebf7911521b9114c9e8f4482bd59175fb35cf06)) by @Tchips46 - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -## Documentation - -- Setup new docs synchro action (#359) ([ff605f2](https://github.com/NanoForge-dev/Engine/commit/ff605f2b38a71f3f4b23707de2809da790e56c90)) by @MartinFillon - -# [@nanoforge-dev/ecs-lib@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-lib@1.1.2...@nanoforge-dev/ecs-lib@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/ecs-lib@1.1.2](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-lib@1.1.1...@nanoforge-dev/ecs-lib@1.1.2) - (2026-04-16) - -## Bug Fixes - -- **ecs-lib:** Component params needs to be ordered (#309) ([c83b04f](https://github.com/NanoForge-dev/Engine/commit/c83b04f3b22f6b5d60a83b822d85c132c3df9652)) by @Tchips46 - -# [@nanoforge-dev/ecs-lib@1.1.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-lib@1.1.0...@nanoforge-dev/ecs-lib@1.1.1) - (2026-04-14) - -## Features - -- **ecs:** Allow component params to be enum (#291) ([59a6697](https://github.com/NanoForge-dev/Engine/commit/59a6697498d7939efdbd65cee4ad5ba77db4d2cd)) by @Tchips46 - -# [@nanoforge-dev/ecs-lib@1.1.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-lib@1.0.1...@nanoforge-dev/ecs-lib@1.1.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- **core-editor:** Hot reload entity component from save (#253) ([71e3699](https://github.com/NanoForge-dev/Engine/commit/71e36998d9f510a874a5c3022aa0cdfa6c6bdfac)) by @Tchips46 - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/ecs-lib@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-lib@1.0.0...@nanoforge-dev/ecs-lib@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/ecs-lib@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/ecs-lib@1.0.0) - (2026-01-09) - -## Bug Fixes - -- **ecs:** Change ecs tests build (#152) ([246759e](https://github.com/NanoForge-dev/Engine/commit/246759ead7bee2364f8405fab50133463ae88978)) by @Exeloo -- **ecs:** Type error in editor manifest (#148) ([389b2d8](https://github.com/NanoForge-dev/Engine/commit/389b2d86ad1515579af94042234ebdf9685bb6ab)) by @MartinFillon - -## Documentation - -- Document registry and setup auto push for docs (#159) ([6d7caa6](https://github.com/NanoForge-dev/Engine/commit/6d7caa63fc78a5269536771d69e027775f1197d2)) by @MartinFillon -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo - -## Features - -- **packages/network:** Client and server for tcp/udp and networked pong as example (#156) ([839fb95](https://github.com/NanoForge-dev/Engine/commit/839fb95449f6ae0ee66d7f7e279374268b743f65)) by @Tchips46 -- Split ecs between client and server (#142) ([18fdd4a](https://github.com/NanoForge-dev/Engine/commit/18fdd4ab8d693ddcd0d3290e9ade127c4f410009)) by @Exeloo - diff --git a/packages/ecs-lib/Makefile b/packages/ecs-lib/Makefile deleted file mode 100644 index 8efa87ce..00000000 --- a/packages/ecs-lib/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -SRC = wasm/SparseArray.cpp\ - wasm/Entity.cpp\ - wasm/Utils.cpp\ - wasm/Registry.cpp - -NAME := libecs - -OUT_DIR = lib -JS_NAME = $(OUT_DIR)/$(NAME).js -WASM_NAME = $(OUT_DIR)/$(NAME).wasm -TS_NAME = $(OUT_DIR)/$(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_NAME) $(WASM_NAME) - -$(TS_NAME) $(JS_NAME) $(WASM_NAME): LDFLAGS += -s MODULARIZE=1 -$(TS_NAME) $(JS_NAME) $(WASM_NAME) &: $(OBJ) - @mkdir -p $(OUT_DIR) - $(CC) $(OBJ) $(LDFLAGS) --emit-tsd libecs-tmp.d.ts -o $(JS_NAME) - cat build/pre.ts > $(TS_NAME) - cat $(OUT_DIR)/libecs-tmp.d.ts >> $(TS_NAME) - $(RM) $(OUT_DIR)/libecs-tmp.d.ts - - -clean: - $(RM) $(OBJ) - $(RM) $(JS_NAME) $(WASM_NAME) - -fclean: clean - -re: fclean all - -.PHONY: re fclean all clean diff --git a/packages/ecs-lib/README.md b/packages/ecs-lib/README.md deleted file mode 100644 index 26e3cb9d..00000000 --- a/packages/ecs-lib/README.md +++ /dev/null @@ -1,56 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/ecs-lib` is a powerful data structure for managing game entities. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/ecs-lib -yarn add @nanoforge-dev/ecs-lib -pnpm add @nanoforge-dev/ecs-lib -bun add @nanoforge-dev/ecs-lib -``` - -## Warning - -This library is not usable on its own. You must use either the [ECS Client][ecs-client] or [ECS Server][ecs-server]. - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/ecs-lib -[npm]: https://www.npmjs.com/package/@nanoforge-dev/ecs-lib -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md -[ecs-client]: https://github.com/NanoForge-dev/Engine/tree/main/packages/ecs-client -[ecs-server]: https://github.com/NanoForge-dev/Engine/tree/main/packages/ecs-server diff --git a/packages/ecs-lib/eslint.config.js b/packages/ecs-lib/eslint.config.js deleted file mode 100644 index 09791c35..00000000 --- a/packages/ecs-lib/eslint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-eslint-config"; - -export default [...config, { ignores: ["build"] }]; diff --git a/packages/ecs-lib/package.json b/packages/ecs-lib/package.json deleted file mode 100644 index d058a130..00000000 --- a/packages/ecs-lib/package.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/ecs-lib", - "version": "1.4.2", - "description": "NanoForge Engine - ECS Lib (source code use by ECS Client and Server)", - "keywords": [ - "nanoforge", - "game", - "engine" - ], - "homepage": "https://github.com/NanoForge-dev/Engine#readme", - "bugs": "https://github.com/NanoForge-dev/Engine/issues", - "license": "MIT", - "contributors": [ - "Bill ", - "Exelo ", - "Fexkoser ", - "Tchips " - ], - "files": [ - "dist", - "lib", - "wasm" - ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", - "exports": { - ".": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "./package.json": "./package.json" - }, - "type": "module", - "directories": { - "lib": "src" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/ecs-lib" - }, - "funding": "https://github.com/NanoForge-dev/Engine?sponsor", - "scripts": { - "build": "tsc --noEmit && tsdown --config-loader unrun", - "clean": "make fclean", - "lint": "prettier --check . && eslint --format=pretty src", - "format": "prettier --write . && eslint --fix --format=pretty src", - "test:unit": "make fclean && make -j 16 && vitest run --config ../../vitest.config.ts", - "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/ecs-lib/*'", - "release": "cliff-jumper", - "docs": "mint-tsdocs generate" - }, - "dependencies": { - "@nanoforge-dev/common": "workspace:*" - }, - "devDependencies": { - "@favware/cliff-jumper": "catalog:ci", - "@nanoforge-dev/utils-eslint-config": "workspace:*", - "@nanoforge-dev/utils-prettier-config": "workspace:*", - "@trivago/prettier-plugin-sort-imports": "catalog:lint", - "@types/node": "catalog:core", - "eslint": "catalog:lint", - "prettier": "catalog:lint", - "tsdown": "catalog:build", - "typescript": "catalog:core", - "unrun": "catalog:build", - "vitest": "catalog:test" - }, - "packageManager": "pnpm@11.24.0", - "engines": { - "node": "26" - }, - "publishConfig": { - "access": "public" - }, - "lint-staged": { - "**": [ - "prettier --ignore-unknown --write" - ], - "src/**/*.ts": [ - "eslint --fix" - ] - } -} diff --git a/packages/ecs-lib/src/ecs-library.abstract.ts b/packages/ecs-lib/src/ecs-library.abstract.ts deleted file mode 100644 index 8914aec0..00000000 --- a/packages/ecs-lib/src/ecs-library.abstract.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { - ASSET_MANAGER_LIBRARY, - BaseComponentSystemLibrary, - type Context, - GRAPHICS_LIBRARY, -} from "@nanoforge-dev/common"; - -import { type MainModule, type Registry } from "../lib/libecs"; - -/** - * Abstract base class for WASM-backed ECS (Entity Component System) libraries. - * - * @remarks - * Loads a compiled `libecs.wasm` binary via the asset manager and initialises - * a `Registry` from the resulting module. Concrete subclasses only need to - * set `this.path` (the asset path to the `.wasm` file) and call `super()` - * — see `ECSClientLibrary` and `ECSServerLibrary`. - * - * Requires the `ASSET_MANAGER_LIBRARY` dependency and runs after - * `GRAPHICS_LIBRARY`. - * - * @example - * ```ts - * // Inside a system's __run hook: - * const ecs = ctx.libraries.getComponentSystem().library; - * const player = ecs.registry.spawnEntity(); - * ecs.registry.addComponent(player, new PositionComponent(0, 0)); - * ``` - */ -export abstract class AbstractECSLibrary extends BaseComponentSystemLibrary { - protected module?: MainModule; - protected _registry?: Registry; - - protected path!: string; - - protected constructor() { - super({ - dependencies: [ASSET_MANAGER_LIBRARY], - runAfter: [GRAPHICS_LIBRARY], - }); - } - - /** @internal */ - abstract override get __name(): string; - - /** @internal */ - async __run(ctx: Context): Promise { - if (!this._registry) this.throwNotInitializedError(); - this._registry.runSystems(ctx); - } - - /** - * The WASM-backed entity/component registry. - * - * @remarks - * Use this to spawn entities, register components, add systems, and query - * component data. - * - * @throws `NfNotInitializedException` When accessed before `__init` has resolved. - */ - get registry(): Registry { - if (!this._registry) this.throwNotInitializedError(); - return this._registry; - } -} diff --git a/packages/ecs-lib/src/editor-manifest.type.ts b/packages/ecs-lib/src/editor-manifest.type.ts deleted file mode 100644 index 337706ad..00000000 --- a/packages/ecs-lib/src/editor-manifest.type.ts +++ /dev/null @@ -1,142 +0,0 @@ -/** - * * Editor Component Element Defaults - * Basic fields for Editor Component Element - * @param Type - Type of the element - * @param Default - Type of the element's default value - */ -type ECSElementDefaults = { - /** - * Type of the element - */ - type: Type; - - /** - * Name of the element - */ - name: string; - - /** - * Description of the element - */ - description?: string; - - /** - * Example of the element - */ - example?: Default; - - /** - * Is the element optional - * @default false - */ - optional?: boolean; - - /** - * Default value of the element - * Force optional to true if set - */ - default?: Default; -}; - -/** - * * Editor Component String Element - * Type for string element - */ -type ECSStringElement = { - /** - * Values allowed for the element - */ - enum?: string[] | Record; -} & ECSElementDefaults<"string", string>; - -/** - * * Editor Component Number Element - * Type for number element - */ -type ECSNumberElement = ECSElementDefaults<"number", number>; - -/** - * * Editor Component Boolean Element - * Type for boolean element - */ -type ECSBooleanElement = ECSElementDefaults<"boolean", boolean>; - -/** - * * Editor Component Asset Element - * Type for asset element - */ -type ECSAssetElement = ECSElementDefaults<"asset", string>; - -/** - * * Editor Component Array Element - * Type for array element - */ -type ECSArrayElement = { - /** - * Items of the array - */ - items: ECSElement; -} & ECSElementDefaults<"array", any[]>; - -/** - * * Editor Component Object Element - * Type for object element - */ -type ECSObjectElement = { - /** - * Properties of the object - */ - properties: Record; -} & ECSElementDefaults<"object", object>; - -/** - * * Editor Component Element - * Type for component element - */ -type ECSElement = - | ECSStringElement - | ECSNumberElement - | ECSBooleanElement - | ECSAssetElement - | ECSArrayElement - | ECSObjectElement; - -/** - * Manifest for a component to be used in the NanoForge Editor - */ -export type EditorComponentManifest = { - /** - * Displayed name of the component - */ - name: string; - - /** - * Description of the component - */ - description?: string; - - /** - * Parameters of the component - */ - params: ECSElement[]; -}; - -/** - * Manifest for a system to be used in the NanoForge Editor - */ -export type EditorSystemManifest = { - /** - * Displayed name of the system - */ - name: string; - - /** - * Description of the system - */ - description?: string; - - /** - * Component names needed by the system - */ - dependencies: string[]; -}; diff --git a/packages/ecs-lib/src/index.ts b/packages/ecs-lib/src/index.ts deleted file mode 100644 index a0d20643..00000000 --- a/packages/ecs-lib/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { AbstractECSLibrary } from "./ecs-library.abstract"; -export type { Component, System, Registry, SparseArray, Entity } from "../lib/libecs"; -export type * from "./editor-manifest.type"; diff --git a/packages/ecs-lib/test/Registry.spec.ts b/packages/ecs-lib/test/Registry.spec.ts deleted file mode 100644 index d85da0e5..00000000 --- a/packages/ecs-lib/test/Registry.spec.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import Module from "../lib/libecs"; - -class Velocity { - name: string = "Velocity"; - constructor( - public x: number, - public y: number, - ) {} -} - -class Position { - name: string = "Position"; - constructor( - public x: number, - public y: number, - ) {} -} - -describe("Registry", () => { - describe("entity management", () => { - it("should spawn an entity with id 0", async () => { - const m = await Module(); - const r = new m.Registry(); - const e = r.spawnEntity(); - expect(e.getId()).toBe(0); - }); - - it("should assign incrementing ids to spawned entities", async () => { - const m = await Module(); - const r = new m.Registry(); - const e0 = r.spawnEntity(); - const e1 = r.spawnEntity(); - expect(e0.getId()).toBe(0); - expect(e1.getId()).toBe(1); - }); - - it("should kill an entity and remove all its components", async () => { - const m = await Module(); - const r = new m.Registry(); - - r.spawnEntity(); - const e = r.spawnEntity(); - expect(e.getId()).toBe(1); - - r.addComponent(e, new Velocity(1, 2)); - r.addComponent(e, new Position(4, 5)); - - r.killEntity(e); - expect(r.getComponents(Velocity).get(e.getId())).toBeUndefined(); - expect(r.getComponents(Position).get(e.getId())).toBeUndefined(); - }); - }); - - describe("component management", () => { - it("should add multiple components to a single entity", async () => { - const m = await Module(); - const r = new m.Registry(); - - const e = r.spawnEntity(); - r.addComponent(e, new Velocity(1, 2)); - r.addComponent(e, new Position(4, 5)); - - expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(1, 2)); - expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(4, 5)); - }); - - it("should override an existing component on an entity", async () => { - const m = await Module(); - const r = new m.Registry(); - - const e = r.spawnEntity(); - r.addComponent(e, new Velocity(1, 2)); - expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(1, 2)); - - r.addComponent(e, new Velocity(4, 5)); - expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(4, 5)); - }); - - it("should remove a component from an entity", async () => { - const m = await Module(); - const r = new m.Registry(); - - const e = r.spawnEntity(); - r.addComponent(e, new Velocity(1, 2)); - 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(); - }); - - it("should reject the reserved 'entity' component name", async () => { - const m = await Module(); - const r = new m.Registry(); - - const e = r.spawnEntity(); - expect(() => r.addComponent(e, { name: "entity" })).toThrow(); - }); - }); - - describe("system management", () => { - it("should run a system that increments a counter", 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); - }); - - it("should run a system that updates positions by velocity", async () => { - const m = await Module(); - const r = new m.Registry(); - - 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); - - 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)); - }); - }); -}); diff --git a/packages/ecs-lib/test/SparseArray.spec.ts b/packages/ecs-lib/test/SparseArray.spec.ts deleted file mode 100644 index 60f669a6..00000000 --- a/packages/ecs-lib/test/SparseArray.spec.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import Module from "../lib/libecs"; - -describe("SparseArray", () => { - describe("instantiation", () => { - it("should create an empty sparse array with size 0", async () => { - const m = await Module(); - const sa = new m.SparseArray(); - expect(sa).toBeDefined(); - expect(sa.size()).toBe(0); - }); - }); - - describe("set and get", () => { - it("should insert a value at index 0 and retrieve it", 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); - }); - - it("should override an existing value at the same index", async () => { - const m = await Module(); - const sa = new m.SparseArray(); - sa.set(0, 42); - sa.set(0, 99); - expect(sa.get(0)).toBe(99); - }); - - it("should store multiple values at different indices", async () => { - const m = await Module(); - const sa = new m.SparseArray(); - sa.set(0, 10); - sa.set(2, 20); - sa.set(4, 30); - expect(sa.get(0)).toBe(10); - expect(sa.get(2)).toBe(20); - expect(sa.get(4)).toBe(30); - }); - }); - - describe("erase", () => { - it("should erase a value and return undefined at that index", 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)).toBeUndefined(); - }); - - it("should only erase the targeted index", async () => { - const m = await Module(); - const sa = new m.SparseArray(); - sa.set(0, 1); - sa.set(1, 2); - sa.erase(0); - expect(sa.get(0)).toBeUndefined(); - expect(sa.get(1)).toBe(2); - }); - }); - - describe("iteration", () => { - it("should sum all values via 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); - }); - - it("should skip erased entries during iteration", async () => { - const m = await Module(); - const sa = new m.SparseArray(); - sa.set(0, 10); - sa.set(1, 20); - sa.set(2, 30); - sa.erase(1); - let sum = 0; - for (let i = 0; i < sa.size(); i++) { - const val = sa.get(i); - if (val !== undefined) sum += val; - } - expect(sum).toBe(40); - }); - }); -}); diff --git a/packages/ecs-lib/test/Zipper.spec.ts b/packages/ecs-lib/test/Zipper.spec.ts deleted file mode 100644 index cd3b1e9a..00000000 --- a/packages/ecs-lib/test/Zipper.spec.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import Module from "../lib/libecs"; - -class Velocity { - name: string = "Velocity"; - constructor( - public x: number, - public y: number, - ) {} -} - -class Position { - name: string = "Position"; - constructor( - public x: number, - public y: number, - ) {} -} - -describe("Zipper", () => { - describe("single component", () => { - it("should zip sequentially spawned entities with one component type", async () => { - const m = await Module(); - const r = new m.Registry(); - - 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) }, - ]); - }); - - it("should zip non-sequential entity ids with one component type", async () => { - const m = await Module(); - const r = new m.Registry(); - - 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[1]).toStrictEqual({ Velocity: new Velocity(1, 1) }); - expect(zip[2]).toStrictEqual({ Velocity: new Velocity(2, 2) }); - expect(zip[3]).toStrictEqual({ Velocity: new Velocity(3, 3) }); - expect(zip[4]).toStrictEqual({ Velocity: new Velocity(4, 4) }); - }); - }); - - describe("multiple components", () => { - it("should only include entities that have all requested components", async () => { - const m = await Module(); - const r = new m.Registry(); - - for (let i = 0; i < 20; i++) { - const e = r.spawnEntity(); - if (i % 5 === 0) r.addComponent(e, new Velocity(0, 1)); - if (i % 3 === 0) r.addComponent(e, new Position(1, 0)); - } - - const zip = r.getZipper([Velocity, Position]); - expect(zip).toBeDefined(); - - for (let i = 0; i < 20; i++) { - if (zip[i]) { - expect(zip[i]).toStrictEqual({ - Velocity: new Velocity(0, 1), - Position: new Position(1, 0), - }); - } - } - }); - }); - - describe("mutations through zipper", () => { - it("should reflect component mutations when zipper is re-fetched", async () => { - const m = await Module(); - const r = new m.Registry(); - - for (let i = 0; i < 20; i++) { - const e = r.spawnEntity(); - if (i % 5 === 0) r.addComponent(e, new Velocity(0, 1)); - } - - let zip = r.getZipper([Velocity]); - expect(zip).toBeDefined(); - - zip.forEach(({ Velocity }) => { - Velocity.y *= 2; - }); - - zip = r.getZipper([Velocity]); - expect(zip).toBeDefined(); - - zip.forEach((entity) => { - expect(entity).toStrictEqual({ Velocity: new Velocity(0, 2) }); - }); - }); - }); - - describe("indexed zipper", () => { - it("should reflect index of the zipped entities components", async () => { - const m = await Module(); - const r = new m.Registry(); - - for (let i = 0; i < 20; i++) { - const e = r.spawnEntity(); - if (i % 5 === 0) r.addComponent(e, new Velocity(0, i)); - } - - const zip = r.getIndexedZipper([Velocity]); - expect(zip).toBeDefined(); - - zip.forEach((entity, index) => { - expect(entity).toStrictEqual({ id: index * 5, Velocity: new Velocity(0, index * 5) }); - }); - }); - }); -}); diff --git a/packages/ecs-server/.nvmrc b/packages/ecs-server/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/ecs-server/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/ecs-server/CHANGELOG.md b/packages/ecs-server/CHANGELOG.md deleted file mode 100644 index b9182d9f..00000000 --- a/packages/ecs-server/CHANGELOG.md +++ /dev/null @@ -1,83 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/ecs-server@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.1.4...@nanoforge-dev/ecs-server@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/ecs-server@1.1.4](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.1.3...@nanoforge-dev/ecs-server@1.1.4) - (2026-04-29) - -## Bug Fixes - -- **render:** Change specific container canva for general html div (#323) ([6ea75f4](https://github.com/NanoForge-dev/Engine/commit/6ea75f4f3c1aa3d2f46bdbea1467f580cb9000bc)) by @Tchips46 - -# [@nanoforge-dev/ecs-server@1.1.3](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.1.2...@nanoforge-dev/ecs-server@1.1.3) - (2026-04-15) - -## Bug Fixes - -- Rollback and remove assets dir in tsup config (#301) ([46df4b9](https://github.com/NanoForge-dev/Engine/commit/46df4b9bb88df445d300fa1bebe65548f1a6231e)) by @Exeloo - -# [@nanoforge-dev/ecs-server@1.1.2](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.1.1...@nanoforge-dev/ecs-server@1.1.2) - (2026-04-15) - -## Bug Fixes - -- Change assets dir to fix wasm import (#298) ([eb33c16](https://github.com/NanoForge-dev/Engine/commit/eb33c166f9ba51a24e97e37b4c43fd14fd61291d)) by @Exeloo - -# [@nanoforge-dev/ecs-server@1.1.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.1.0...@nanoforge-dev/ecs-server@1.1.1) - (2026-04-14) - -## Features - -- **ecs:** Allow component params to be enum (#291) ([59a6697](https://github.com/NanoForge-dev/Engine/commit/59a6697498d7939efdbd65cee4ad5ba77db4d2cd)) by @Tchips46 - -# [@nanoforge-dev/ecs-server@1.1.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.0.1...@nanoforge-dev/ecs-server@1.1.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- **core-editor:** Hot reload entity component from save (#253) ([71e3699](https://github.com/NanoForge-dev/Engine/commit/71e36998d9f510a874a5c3022aa0cdfa6c6bdfac)) by @Tchips46 - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/ecs-server@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/ecs-server@1.0.0...@nanoforge-dev/ecs-server@1.0.1) - (2026-02-16) - -## Bug Fixes - -- Add permissions to ci and change release process (#179) ([91b8832](https://github.com/NanoForge-dev/Engine/commit/91b88329d61fd96305c5868d39589439cfa08814)) by @Exeloo - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/ecs-server@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/ecs-server@0.0.1) - (2026-01-09) - -## Bug Fixes - -- **ecs:** Change ecs tests build (#152) ([246759e](https://github.com/NanoForge-dev/Engine/commit/246759ead7bee2364f8405fab50133463ae88978)) by @Exeloo - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo - -## Features - -- Split ecs between client and server (#142) ([18fdd4a](https://github.com/NanoForge-dev/Engine/commit/18fdd4ab8d693ddcd0d3290e9ade127c4f410009)) by @Exeloo - diff --git a/packages/ecs-server/Makefile b/packages/ecs-server/Makefile deleted file mode 100644 index 4b31107c..00000000 --- a/packages/ecs-server/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -BASE_DIR = node_modules/@nanoforge-dev/ecs-lib - -SRC = $(BASE_DIR)/wasm/SparseArray.cpp\ - $(BASE_DIR)/wasm/Entity.cpp\ - $(BASE_DIR)/wasm/Utils.cpp\ - $(BASE_DIR)/wasm/Registry.cpp - -NAME := libecs - -OUT_DIR = lib -JS_NAME = $(OUT_DIR)/$(NAME).js -WASM_NAME = $(OUT_DIR)/$(NAME).wasm -TS_NAME = $(OUT_DIR)/$(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_NAME) $(WASM_NAME) - -$(TS_NAME) $(JS_NAME) $(WASM_NAME): LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s ENVIRONMENT=node -$(TS_NAME) $(JS_NAME) $(WASM_NAME) &: $(OBJ) - @mkdir -p $(OUT_DIR) - $(CC) $(OBJ) $(LDFLAGS) -o $(JS_NAME) - cp $(BASE_DIR)/$(TS_NAME) $(TS_NAME) - -clean: - $(RM) $(OBJ) - $(RM) $(JS_NAME) $(WASM_NAME) $(TS_NAME) - -fclean: clean - -tests: LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -tests: $(OBJ) - @mkdir -p $(OUT_DIR) - $(CC) $(OBJ) $(LDFLAGS) -o $(JS_NAME) - cp $(BASE_DIR)/$(TS_NAME) $(TS_NAME) - -re: fclean all - -.PHONY: re fclean all clean tests diff --git a/packages/ecs-server/README.md b/packages/ecs-server/README.md deleted file mode 100644 index 104b97e6..00000000 --- a/packages/ecs-server/README.md +++ /dev/null @@ -1,125 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/ecs-server` is a wrapper of `@nanoforge-dev/ecs-lib` for server-side usage. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/ecs-server -yarn add @nanoforge-dev/ecs-server -pnpm add @nanoforge-dev/ecs-server -bun add @nanoforge-dev/ecs-server -``` - -## Example usage - -Initialize the library in your main file. - -```ts -import { type IRunOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSServerLibrary } from "@nanoforge-dev/ecs-server"; - -export async function main(options: IRunServerOptions) { - const app = NanoforgeFactory.createServer(); - - const ecs = new ECSServerLibrary(); - - app.useComponentSystem(ecs); - - await app.init(options); - - const registry = ecs.registry; - - const entity = registry.spawnEntity(); - registry.addComponent(entity, new ExampleComponent("foo", 42)); - - registry.addSystem(exampleSystem); - - await app.run(); -} -``` - -With component - -```ts -export class ExampleComponent { - name = this.constructor.name; - - constructor( - public paramA: string, - public paramB: number, - public paramC: boolean = false, - ) {} - - get foo() { - return "bar"; - } - - get paramAOrDefault() { - return this.paramC ? this.paramA : "default"; - } - - addOne() { - this.paramB += 1; - } -} -``` - -And system - -```ts -export const exampleSystem = (registry: Registry, ctx: Context) => { - const entities = registry.getZipper([ExampleComponent]); - - entities.forEach((entity) => { - if (entity.ExampleComponent.paramA === "end") { - ctx.app.setIsRunning(false); - return; - } - - if (entity.ExampleComponent.paramB === 0) entity.ExampleComponent.paramA = "end"; - - if (entity.ExampleComponent.paramB >= 0) - entity.ExampleComponent.paramB = entity.ExampleComponent.paramB - 1; - }); -}; -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/ecs-server -[npm]: https://www.npmjs.com/package/@nanoforge-dev/ecs-server -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/ecs-server/package.json b/packages/ecs-server/package.json deleted file mode 100644 index d6c2f8bd..00000000 --- a/packages/ecs-server/package.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/ecs-server", - "version": "1.4.2", - "description": "NanoForge Engine - ECS Server", - "keywords": [ - "nanoforge", - "game", - "engine" - ], - "homepage": "https://github.com/NanoForge-dev/Engine#readme", - "bugs": "https://github.com/NanoForge-dev/Engine/issues", - "license": "MIT", - "contributors": [ - "Bill ", - "Exelo ", - "Fexkoser ", - "Tchips " - ], - "files": [ - "dist", - "lib", - "wasm" - ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", - "exports": { - ".": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "./package.json": "./package.json" - }, - "type": "module", - "directories": { - "lib": "src" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/ecs-server" - }, - "funding": "https://github.com/NanoForge-dev/Engine?sponsor", - "scripts": { - "build": "pnpm build:wasm && pnpm build:script", - "build:script": "tsc --noEmit && tsdown --config-loader unrun", - "build:wasm": "make", - "clean": "make fclean", - "lint": "prettier --check . && eslint --format=pretty src", - "format": "prettier --write . && eslint --fix --format=pretty src", - "test:unit": "make fclean && make tests -j 16 && vitest run --config ../../vitest.config.ts && make fclean", - "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/ecs-server/*'", - "release": "cliff-jumper", - "docs": "mint-tsdocs generate" - }, - "dependencies": { - "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/ecs-lib": "workspace:*" - }, - "devDependencies": { - "@favware/cliff-jumper": "catalog:ci", - "@nanoforge-dev/asset-manager": "workspace:*", - "@nanoforge-dev/core": "workspace:*", - "@nanoforge-dev/utils-eslint-config": "workspace:*", - "@nanoforge-dev/utils-prettier-config": "workspace:*", - "@trivago/prettier-plugin-sort-imports": "catalog:lint", - "@types/node": "catalog:core", - "eslint": "catalog:lint", - "prettier": "catalog:lint", - "tsdown": "catalog:build", - "typescript": "catalog:core", - "unrun": "catalog:build", - "vitest": "catalog:test" - }, - "packageManager": "pnpm@11.24.0", - "engines": { - "node": "26" - }, - "publishConfig": { - "access": "public" - }, - "lint-staged": { - "**": [ - "prettier --ignore-unknown --write" - ], - "src/**/*.ts": [ - "eslint --fix" - ] - } -} diff --git a/packages/ecs-server/src/ecs-server-library.ts b/packages/ecs-server/src/ecs-server-library.ts deleted file mode 100644 index efa17691..00000000 --- a/packages/ecs-server/src/ecs-server-library.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { type InitContext } from "@nanoforge-dev/common"; -import { AbstractECSLibrary } from "@nanoforge-dev/ecs-lib"; - -import { default as Module } from "../lib/libecs"; - -/** - * Server-side ECS library backed by the compiled WASM module. - * - * @remarks - * Loads `libecs.wasm` from the asset manager and initialises the entity - * registry. Register with the application: - * - * ```ts - * server.useComponentSystem(new ECSServerLibrary()); - * ``` - * - * Access the registry in game code: - * ```ts - * const ecs = ctx.libraries.getComponentSystem().library; - * const entity = ecs.registry.spawnEntity(); - * ``` - */ -export class ECSServerLibrary extends AbstractECSLibrary { - constructor() { - super(); - this.path = "libecs.wasm"; - } - - /** @internal */ - get __name(): string { - return "ECSLibrary"; - } - - /** @internal */ - override async __init(context: InitContext): Promise { - const wasmFile = context.libraries.getAssetManager().library.getAsset(this.path); - this.module = await Module({ locateFile: () => wasmFile.path }); - this._registry = new this.module.Registry(); - } -} diff --git a/packages/ecs-server/src/index.ts b/packages/ecs-server/src/index.ts deleted file mode 100644 index 201a78ca..00000000 --- a/packages/ecs-server/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import ECSModule from "../lib/libecs"; -// @ts-ignore -import "../lib/libecs.wasm"; - -export type { - Component, - EditorComponentManifest, - EditorSystemManifest, - System, - Registry, - Entity, - SparseArray, -} from "@nanoforge-dev/ecs-lib"; - -export { ECSServerLibrary } from "./ecs-server-library"; - -export const Module = ECSModule; diff --git a/packages/ecs-server/test/ecs-server-library.spec.ts b/packages/ecs-server/test/ecs-server-library.spec.ts deleted file mode 100644 index 42a9ed41..00000000 --- a/packages/ecs-server/test/ecs-server-library.spec.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { ClearContext, type IConfigRegistry, InitContext } from "@nanoforge-dev/common"; -import { beforeAll, beforeEach, describe, expect, it } from "vitest"; - -import { EditableApplicationContext } from "../../core/src/common/context/contexts/application.editable-context"; -import { EditableLibraryManager } from "../../core/src/common/library/manager/library.manager"; -import { type Registry } from "../lib/libecs"; -import { ECSServerLibrary } from "../src/ecs-server-library"; - -class Position { - name: string = "Position"; - constructor( - public x: number, - public y: number, - ) {} -} - -class Velocity { - name: string = "Velocity"; - constructor( - public x: number, - public y: number, - ) {} -} - -const getRunSystemsParams = (registry: Registry) => ({ - libs: { getComponentSystem: () => ({ registry }) }, -}); - -const assetManager = new AssetManagerLibrary(); -const libraryManager = new EditableLibraryManager(); -const appContext = new EditableApplicationContext(libraryManager); -const configRegistry = {} as IConfigRegistry; -const initContext = new InitContext(appContext, libraryManager, configRegistry, { - // @ts-ignore - container: null, - files: new Map([["/libecs.wasm", "./lib/libecs.wasm"]]), -}); -const clearContext = new ClearContext(appContext, libraryManager); -libraryManager.setAssetManager(assetManager); - -describe("ECSServerLibrary", () => { - let ecs: ECSServerLibrary; - let registry: Registry; - - beforeAll(async () => { - await assetManager.__init(initContext); - }); - - beforeEach(async () => { - ecs = new ECSServerLibrary(); - await ecs.__init(initContext); - registry = ecs.registry; - }); - - describe("metadata", () => { - it("should expose the correct library name", () => { - expect(ecs.__name).toBe("ECSLibrary"); - }); - }); - - describe("entity management", () => { - it("should spawn an entity with id 0", () => { - const entity = registry.spawnEntity(); - expect(entity).toBeDefined(); - expect(entity.getId()).toBe(0); - }); - - it("should assign incrementing ids to spawned entities", () => { - const e0 = registry.spawnEntity(); - const e1 = registry.spawnEntity(); - const e2 = registry.spawnEntity(); - expect(e0.getId()).toBe(0); - expect(e1.getId()).toBe(1); - expect(e2.getId()).toBe(2); - }); - - it("should kill an entity and remove its components", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.killEntity(entity); - expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); - }); - - it("should kill an entity with multiple components", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.addComponent(entity, new Velocity(3, 4)); - registry.killEntity(entity); - expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); - expect(registry.getComponents(Velocity).get(entity.getId())).toBeUndefined(); - }); - }); - - describe("component management", () => { - it("should add a component to an entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( - new Position(1, 2), - ); - }); - - it("should override a component on an entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.addComponent(entity, new Position(9, 9)); - expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( - new Position(9, 9), - ); - }); - - it("should add multiple component types to the same entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(3, 4)); - registry.addComponent(entity, new Velocity(1, 0)); - expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( - new Position(3, 4), - ); - expect(registry.getComponents(Velocity).get(entity.getId())).toStrictEqual( - new Velocity(1, 0), - ); - }); - - it("should remove a component from an entity", () => { - const entity = registry.spawnEntity(); - registry.addComponent(entity, new Position(1, 2)); - registry.removeComponent(entity, Position); - expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); - }); - - it("should track component count across multiple entities", () => { - const e0 = registry.spawnEntity(); - const e1 = registry.spawnEntity(); - registry.addComponent(e0, new Position(0, 0)); - registry.addComponent(e1, new Position(1, 1)); - expect(registry.getComponents(Position).size()).toBe(2); - }); - }); - - describe("system management", () => { - it("should run a registered system once per call", () => { - let counter = 0; - registry.addSystem(() => { - counter += 1; - }); - registry.runSystems(getRunSystemsParams(registry)); - expect(counter).toBe(1); - }); - - it("should run all registered systems in order", () => { - const order: number[] = []; - registry.addSystem(() => order.push(1)); - registry.addSystem(() => order.push(2)); - registry.runSystems(getRunSystemsParams(registry)); - expect(order).toStrictEqual([1, 2]); - }); - - it("should run systems multiple times across multiple calls", () => { - let counter = 0; - registry.addSystem(() => { - counter += 1; - }); - for (let i = 0; i < 5; i++) { - registry.runSystems(getRunSystemsParams(registry)); - } - expect(counter).toBe(5); - }); - }); - - describe("lifecycle", () => { - it("should clear without error", async () => { - await expect(ecs.__clear(clearContext)).resolves.not.toThrow(); - }); - }); -}); diff --git a/packages/ecs-server/tsconfig.json b/packages/ecs-server/tsconfig.json deleted file mode 100644 index 2690c0ff..00000000 --- a/packages/ecs-server/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig.json", - "extends": "../../tsconfig.json", - "compilerOptions": { - "types": ["node"], - "declaration": true, - "paths": { - "/snippets/*": ["./docs/snippets/*"] - } - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist"], - "mdx": { - "checkMdx": true - } -} diff --git a/packages/graphics-2d-editor/.cliff-jumperrc.json b/packages/graphics-2d-editor/.cliff-jumperrc.json deleted file mode 100644 index b68e4434..00000000 --- a/packages/graphics-2d-editor/.cliff-jumperrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "graphics-2d-editor", - "org": "nanoforge-dev", - "packagePath": "packages/graphics-2d-editor", - "tagTemplate": "{{new-version}}", - "identifierBase": false -} diff --git a/packages/graphics-2d-editor/.nvmrc b/packages/graphics-2d-editor/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/graphics-2d-editor/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/graphics-2d-editor/CHANGELOG.md b/packages/graphics-2d-editor/CHANGELOG.md deleted file mode 100644 index c3bbb93e..00000000 --- a/packages/graphics-2d-editor/CHANGELOG.md +++ /dev/null @@ -1,17 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Features - -- Add drag and drop on graphics (#380) ([afffa7a](https://github.com/NanoForge-dev/Engine/commit/afffa7afd1f51eba2d2cd0d96fe47e5db04ac534)) by @Exeloo - -# Changelog - -All notable changes to this project will be documented in this file. diff --git a/packages/graphics-2d-editor/README.md b/packages/graphics-2d-editor/README.md deleted file mode 100644 index 59e503c6..00000000 --- a/packages/graphics-2d-editor/README.md +++ /dev/null @@ -1,98 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/graphics-2d-editor` is an addon for the [NanoForge Graphics 2D library][graphics] to handle the creation of 2D graphics games in the editor. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/graphics-2d-editor -yarn add @nanoforge-dev/graphics-2d-editor -pnpm add @nanoforge-dev/graphics-2d-editor -bun add @nanoforge-dev/graphics-2d-editor -``` - -## Example usage - -Initialize the library in your main file (for the rest of the example, please refer to the graphics 2D library [documentation][graphics]). - -```ts -import { type IRunClientOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSClientLibrary } from "@nanoforge-dev/ecs-client"; -import { Circle, Graphics2DLibrary, Layer } from "@nanoforge-dev/graphics-2d"; -import { Graphics2DEditorLibrary } from "@nanoforge-dev/graphics-2d-editor"; - -import { CircleComponent } from "./components/CircleComponent"; - -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const ecs = new ECSClientLibrary(); - const graphics = new Graphics2DLibrary(); - const graphicsEditor = new Graphics2DEditorLibrary(); - - app.useComponentSystem(ecs); - app.useGraphics(graphics); - app.use(Symbol.for("GraphicsEditor"), graphicsEditor); - - await app.init(options); - - const registry = ecs.registry; - - const layer = new Layer(); - graphics.stage.add(layer); - - const entity = registry.spawnEntity(); - registry.addComponent( - entity, - new CircleComponent( - new Circle({ - radius: 70, - fill: "red", - }), - layer, - ), - ); - - await app.run(); -} -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/graphics-2d-editor -[graphics]: https://github.com/NanoForge-dev/Engine/tree/main/packages/graphics-2d -[npm]: https://www.npmjs.com/package/@nanoforge-dev/graphics-2d-editor -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/graphics-2d-editor/package.json b/packages/graphics-2d-editor/package.json deleted file mode 100644 index 79b29a2b..00000000 --- a/packages/graphics-2d-editor/package.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/graphics-2d-editor", - "version": "1.4.2", - "description": "NanoForge Engine - Graphics-2d Editor", - "keywords": [ - "nanoforge", - "game", - "engine" - ], - "homepage": "https://github.com/NanoForge-dev/Engine#readme", - "bugs": "https://github.com/NanoForge-dev/Engine/issues", - "license": "MIT", - "contributors": [ - "Bill ", - "Exelo ", - "Fexkoser ", - "Tchips " - ], - "files": [ - "dist" - ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", - "exports": { - ".": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "./package.json": "./package.json" - }, - "type": "module", - "directories": { - "lib": "src" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/graphics-2d-editor" - }, - "funding": "https://github.com/NanoForge-dev/Engine?sponsor", - "scripts": { - "build": "tsc --noEmit && tsdown --config-loader unrun", - "lint": "prettier --check . && eslint --format=pretty src", - "format": "prettier --write . && eslint --fix --format=pretty src", - "test:unit": "vitest run --config ../../vitest.config.ts", - "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/graphics-2d-editor/*'", - "release": "cliff-jumper", - "docs": "mint-tsdocs generate" - }, - "dependencies": { - "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/core-editor": "workspace:*", - "@nanoforge-dev/ecs-lib": "workspace:*" - }, - "devDependencies": { - "@favware/cliff-jumper": "catalog:ci", - "@nanoforge-dev/utils-eslint-config": "workspace:*", - "@nanoforge-dev/utils-prettier-config": "workspace:*", - "@trivago/prettier-plugin-sort-imports": "catalog:lint", - "eslint": "catalog:lint", - "prettier": "catalog:lint", - "tsdown": "catalog:build", - "typescript": "catalog:core", - "unrun": "catalog:build", - "vitest": "catalog:test" - }, - "packageManager": "pnpm@11.24.0", - "engines": { - "node": "26" - }, - "publishConfig": { - "access": "public" - }, - "lint-staged": { - "**": [ - "prettier --ignore-unknown --write" - ], - "src/**/*.ts": [ - "eslint --fix" - ] - } -} diff --git a/packages/graphics-2d-editor/src/graphics-2d-editor.library.ts b/packages/graphics-2d-editor/src/graphics-2d-editor.library.ts deleted file mode 100644 index 0c02202a..00000000 --- a/packages/graphics-2d-editor/src/graphics-2d-editor.library.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { - COMPONENT_SYSTEM_LIBRARY, - GRAPHICS_LIBRARY, - type InitContext, - Library, -} from "@nanoforge-dev/common"; -import { EditorEvents, type EventEmitter } from "@nanoforge-dev/core-editor"; -import type { AbstractECSLibrary, Registry } from "@nanoforge-dev/ecs-lib"; - -export class Graphics2DEditorLibrary extends Library { - private _eventEmitter?: EventEmitter; - private _initComponents: Map> = new Map(); - - constructor() { - super({ - dependencies: [COMPONENT_SYSTEM_LIBRARY, GRAPHICS_LIBRARY], - }); - } - - /** @internal */ - get __name(): string { - return "Graphics2DEditorLibrary"; - } - - /** @internal */ - public override async __init(context: InitContext): Promise { - this._eventEmitter = context.eventEmitter; - const reg = context.libraries.getComponentSystem().library.registry; - reg.addSystem(this._dragSystem.bind(this)); - } - - private _dragSystem(registry: Registry) { - if (!this._eventEmitter) return; - - const entities = [ - ...registry.getZipper([{ name: "__RESERVED_entityId" }, { name: "DrawableCircle2D" }]), - ...registry.getZipper([{ name: "__RESERVED_entityId" }, { name: "DrawableRect2D" }]), - ...registry.getZipper([{ name: "__RESERVED_entityId" }, { name: "DrawableText2D" }]), - ]; - entities.forEach( - ({ __RESERVED_entityId, DrawableCircle2D, DrawableRect2D, DrawableText2D }: any) => { - const entityId = __RESERVED_entityId.entityId; - if (!this._initComponents.has(entityId)) this._initComponents.set(entityId, new Set()); - const s = this._initComponents.get(entityId) as Set; - [DrawableCircle2D, DrawableRect2D, DrawableText2D].forEach((comp) => { - if (!comp) return; - if (!s.has(comp.name)) { - comp.shape.draggable(true); - comp.shape.on("dragend", ({ target }: any) => { - this._eventEmitter?.emit( - EditorEvents.MOVE_COMPONENT, - entityId, - comp.name, - target._lastPos, - ); - }); - s.add(comp.name); - } - }); - }, - ); - } -} diff --git a/packages/graphics-2d-editor/src/index.ts b/packages/graphics-2d-editor/src/index.ts deleted file mode 100644 index b187dac1..00000000 --- a/packages/graphics-2d-editor/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Graphics2DEditorLibrary } from "./graphics-2d-editor.library"; diff --git a/packages/graphics-2d/.nvmrc b/packages/graphics-2d/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/graphics-2d/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/graphics-2d/CHANGELOG.md b/packages/graphics-2d/CHANGELOG.md deleted file mode 100644 index d011c595..00000000 --- a/packages/graphics-2d/CHANGELOG.md +++ /dev/null @@ -1,101 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Bug Fixes - -- **core-editor:** Run when don't paused (#377) ([09147d2](https://github.com/NanoForge-dev/Engine/commit/09147d2e71488c7028e1f5983f43d5ff724769ee)) by @Tchips46 - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -## Features - -- **core-editor:** Event listenner not runned if main loop is paused (#379) ([25053db](https://github.com/NanoForge-dev/Engine/commit/25053db388e277bc7e1181315f07249f121fcc94)) by @Tchips46 -- **graphic-2d:** Destroy konva js in the lib clear (#372) ([e1ae678](https://github.com/NanoForge-dev/Engine/commit/e1ae678e7420eb20a2152fc110550b786877e7a5)) by @Tchips46 - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/graphics-2d@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/graphics-2d@1.0.3...@nanoforge-dev/graphics-2d@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/graphics-2d@1.0.3](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/graphics-2d@1.0.2...@nanoforge-dev/graphics-2d@1.0.3) - (2026-04-29) - -## Bug Fixes - -- **render:** Change specific container canva for general html div (#323) ([6ea75f4](https://github.com/NanoForge-dev/Engine/commit/6ea75f4f3c1aa3d2f46bdbea1467f580cb9000bc)) by @Tchips46 - -# [@nanoforge-dev/graphics-2d@1.0.2](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/graphics-2d@1.0.1...@nanoforge-dev/graphics-2d@1.0.2) - (2026-04-19) - -## Features - -- **graphics:** Add base layer and change stage size to fit the original canva (#312) ([3e9bc83](https://github.com/NanoForge-dev/Engine/commit/3e9bc83c7ba27f3636139fa858da35810dd90c2d)) by @Tchips46 -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/graphics-2d@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/graphics-2d@1.0.0...@nanoforge-dev/graphics-2d@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/graphics-2d@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/graphics-2d@1.0.0) - (2026-01-09) - -## Bug Fixes - -- Issues caused by the new build method (#122) ([b5b4fc3](https://github.com/NanoForge-dev/Engine/commit/b5b4fc3fa546067017db8f56603b76df0345bbcf)) by @Exeloo -- **graphics-2d, ecs:** Update type handling in vertex buffer and library init test ([6e44a2c](https://github.com/NanoForge-dev/Engine/commit/6e44a2cae0ab3a3cff5908389765a512ca9bd2d7)) by @Exeloo -- **graphics:** Game loop ([53329d2](https://github.com/NanoForge-dev/Engine/commit/53329d28c47bfac9fe86259e9fc6f42b206062a8)) by @Exeloo -- **graphics:** Fix tests ([0adefdf](https://github.com/NanoForge-dev/Engine/commit/0adefdfde6b9d7e3d6fa08384be9e46c7722ff5b)) by @Exeloo -- **graphics:** Fix display ([d8522e5](https://github.com/NanoForge-dev/Engine/commit/d8522e56678f3bd136733f7941c1d917c18b1400)) by @Exeloo -- **common:** Change is running ([ed54f84](https://github.com/NanoForge-dev/Engine/commit/ed54f847073f37188b7a11f3e39035e4c8c30918)) by @Exeloo -- **ecs:** Change type handling on lib ecs ([580192d](https://github.com/NanoForge-dev/Engine/commit/580192d5038f386c965434f78aacdf3d1e399ff8)) by @Exeloo - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo -- Add a basic introduction readme ([b240964](https://github.com/NanoForge-dev/Engine/commit/b240964a265b31769a8c5422e23e20156ba56192)) by @MartinFillon -- Add building and dependency docs to every readme ([2d4785b](https://github.com/NanoForge-dev/Engine/commit/2d4785bdcb455e83337b37540f9ab6b3394c0850)) by @MartinFillon - -## Features - -- **core:** Introduce `EditableApplicationContext` for managing sound libraries ([6c7bac2](https://github.com/NanoForge-dev/Engine/commit/6c7bac261eeb7ad79203d5695d5ad76dc9e9e9f5)) by @Exeloo -- **example:** Update `pong` game mechanics and graphics integration ([835fb7d](https://github.com/NanoForge-dev/Engine/commit/835fb7dae51660f6c8918cce0486d3624e4b4512)) by @Exeloo -- Add dependencies handling ([e51dd3b](https://github.com/NanoForge-dev/Engine/commit/e51dd3bdb5e2e3de21339bf6218e85f935efb9d5)) by @Exeloo -- Add dependencies to current libs ([9a838dc](https://github.com/NanoForge-dev/Engine/commit/9a838dcfdacd690b889ead64df730d7d35802f91)) by @Exeloo -- **graphics:** Add dynamic size handle of canvas ([047bf0f](https://github.com/NanoForge-dev/Engine/commit/047bf0f61386dba06948cc70b419bcc9e5f4c900)) by @Exeloo -- **graphics:** Add rectangle ([396831d](https://github.com/NanoForge-dev/Engine/commit/396831d511ad59fb2fc4b0266a5092891c9a5d37)) by @Exeloo -- **template:** Add scripts to template ([6ec5066](https://github.com/NanoForge-dev/Engine/commit/6ec5066604cb0ee48fb4e31fe4eca3f425f47d3c)) by @Exeloo -- **game:** Add width and height ([c93c985](https://github.com/NanoForge-dev/Engine/commit/c93c985665bd99c09bc410f1499d11aeaffe3c4c)) by @Exeloo -- **game:** Add graphics factory ([0f4453c](https://github.com/NanoForge-dev/Engine/commit/0f4453ced908b39e953a672324e97eba82bfeaa3)) by @Exeloo -- **graphics:** Add base component and circle component ([28f5c45](https://github.com/NanoForge-dev/Engine/commit/28f5c45229bd525deaca3aacb341e2633be46ea4)) by @Exeloo -- **graphics-2d:** Add base library ([e39a798](https://github.com/NanoForge-dev/Engine/commit/e39a79815eed5faacc38150cf5486e8708d9a486)) by @Exeloo - -## Refactor - -- Change test engine (#126) ([ce2c71f](https://github.com/NanoForge-dev/Engine/commit/ce2c71fc1d1b5e3fb3ff4e86fd30aa77c969fbe0)) by @Exeloo -- Migrate namespaces to `@nanoforge-dev` and update related imports ([c84c927](https://github.com/NanoForge-dev/Engine/commit/c84c927ead941d914e5a9fd752fd3a5ac969f981)) by @Exeloo -- **libraries:** Implement initialization validation and standardize nullable fields ([8b04575](https://github.com/NanoForge-dev/Engine/commit/8b04575cf7f649a440b8f40ad6114414406b0c1a)) by @Exeloo -- **libs:** Remove `ECSContext` type in favor of `Context` ([b4ea6f1](https://github.com/NanoForge-dev/Engine/commit/b4ea6f1622b4a29cf57b9bfa1b715f56d248806e)) by @Exeloo -- **graphics-2d:** Remove custom rendering core and replace with `Konva` ([278c745](https://github.com/NanoForge-dev/Engine/commit/278c745d8306bc922b1069dce46a29dab2ceff33)) by @Exeloo - -## Testing - -- Refactor context initialization and asset handling in library tests ([3864643](https://github.com/NanoForge-dev/Engine/commit/38646439ed40dac4d190829e3839228d0e2605fa)) by @Exeloo -- **libs:** Include ConfigRegistry in library initialization test ([b559759](https://github.com/NanoForge-dev/Engine/commit/b5597595087b42132f491cc59ace69d63394c178)) by @Exeloo - diff --git a/packages/graphics-2d/src/graphics-2d.library.ts b/packages/graphics-2d/src/graphics-2d.library.ts deleted file mode 100644 index f8b2959b..00000000 --- a/packages/graphics-2d/src/graphics-2d.library.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { BaseGraphicsLibrary, type InitContext } from "@nanoforge-dev/common"; - -import * as Graphics from "./exports/konva"; - -/** - * Built-in 2D graphics library powered by [Konva](https://konvajs.org/). - * - * @remarks - * Creates a full-window Konva `Stage` and a default `Layer` during - * initialisation. Game code interacts with the stage and layer directly to - * add shapes, images, and animations. Register with the application: - * - * ```ts - * client.useGraphics(new Graphics2DLibrary()); - * ``` - * - * Access in game code: - * ```ts - * const gfx = ctx.libraries.getGraphics().library; - * const rect = new Konva.Rect(`x: 10, y: 10, width: 100, height: 50, fill: "red" `); - * gfx.baseLayer.add(rect); - * ``` - */ -export class Graphics2DLibrary extends BaseGraphicsLibrary { - private _stage?: Graphics.Stage; - private _baseLayer?: Graphics.Layer; - - /** @internal */ - get __name(): string { - return "Graphics2DLibrary"; - } - - /** - * The Konva `Stage` that covers the container element. - * - * @remarks - * Initialised to the container's `offsetWidth` × `offsetHeight` dimensions. - * - * @throws `NfNotInitializedException` When accessed before `__init` has resolved. - */ - get stage(): Graphics.Stage { - if (!this._stage) this.throwNotInitializedError(); - return this._stage; - } - - /** - * The default Konva `Layer` automatically added to the stage. - * - * @remarks - * Add shapes and nodes to this layer for them to appear on screen. - * - * @throws `NfNotInitializedException` When accessed before `__init` has resolved. - */ - get baseLayer(): Graphics.Layer { - if (!this._baseLayer) this.throwNotInitializedError(); - return this._baseLayer; - } - - /** @internal */ - public override async __init(context: InitContext): Promise { - if (!context.container) { - throw new Error("Can't initialize the container context"); - } - this._stage = new Graphics.Stage({ - container: context.container, - width: context.container.offsetWidth, - height: context.container.offsetHeight, - }); - this._baseLayer = new Graphics.Layer(); - this._stage.add(this._baseLayer); - } - - /** @internal */ - public async __run(): Promise {} - - /** @internal */ - public override async __clear(): Promise { - this._stage?.destroy(); - delete (window as any).Konva; - } -} diff --git a/packages/graphics-2d/src/index.ts b/packages/graphics-2d/src/index.ts deleted file mode 100644 index 19bbac51..00000000 --- a/packages/graphics-2d/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Graphics2DLibrary } from "./graphics-2d.library"; -export * from "./exports/konva"; diff --git a/packages/graphics-2d/test/graphics-2d.library.spec.ts b/packages/graphics-2d/test/graphics-2d.library.spec.ts deleted file mode 100644 index 0259c538..00000000 --- a/packages/graphics-2d/test/graphics-2d.library.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { type IConfigRegistry, InitContext } from "@nanoforge-dev/common"; -import { beforeEach, describe, expect, it } from "vitest"; - -import { EditableApplicationContext } from "../../core/src/common/context/contexts/application.editable-context"; -import { EditableLibraryManager } from "../../core/src/common/library/manager/library.manager"; -import { Graphics2DLibrary } from "../src"; - -const makeContext = (container: HTMLDivElement | null) => { - const libraryManager = new EditableLibraryManager(); - const appContext = new EditableApplicationContext(libraryManager); - const configRegistry = {} as IConfigRegistry; - return new InitContext(appContext, libraryManager, configRegistry, { - // @ts-ignore - container, - files: new Map(), - }); -}; - -describe("Graphics2DLibrary", () => { - describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new Graphics2DLibrary().__name).toBe("Graphics2DLibrary"); - }); - }); - - describe("before initialization", () => { - let library: Graphics2DLibrary; - - beforeEach(() => { - library = new Graphics2DLibrary(); - }); - - it("should throw when stage is accessed before __init", () => { - expect(() => library.stage).toThrow(); - }); - - it("should throw when layer is accessed before __init", () => { - expect(() => library.baseLayer).toThrow(); - }); - - it("should throw when __init is called with a null container", async () => { - await expect(library.__init(makeContext(null))).rejects.toThrow(); - }); - }); -}); diff --git a/packages/graphics-2d/tsdown.config.ts b/packages/graphics-2d/tsdown.config.ts deleted file mode 100644 index 12f5dea6..00000000 --- a/packages/graphics-2d/tsdown.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createTsdownConfig } from "../../tsdown.config"; - -export default [createTsdownConfig()]; diff --git a/packages/input/.nvmrc b/packages/input/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/input/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/input/CHANGELOG.md b/packages/input/CHANGELOG.md deleted file mode 100644 index 1746b049..00000000 --- a/packages/input/CHANGELOG.md +++ /dev/null @@ -1,71 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/input@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/input@1.0.2...@nanoforge-dev/input@1.3.0) - (2026-05-26) - -## Features - -- **input:** Add mouse input event in input library (#332) ([39c185d](https://github.com/NanoForge-dev/Engine/commit/39c185d935771ddeae6d293e3a6e6f4096de3cf2)) by @bill-h4rper - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/input@1.0.2](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/input@1.0.1...@nanoforge-dev/input@1.0.2) - (2026-04-14) - -## Bug Fixes - -- **input:** Get key always return boolean (#289) ([7c659db](https://github.com/NanoForge-dev/Engine/commit/7c659db0b9c965b7c65668b9864e7c0c575793d3)) by @Tchips46 - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/input@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/input@1.0.0...@nanoforge-dev/input@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/input@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/input@1.0.0) - (2026-01-09) - -## Bug Fixes - -- **input:** Initialized input handler record to prevent undefined ([d03f475](https://github.com/NanoForge-dev/Engine/commit/d03f475721306659e74880fad3fbacc96a105e03)) by @MartinFillon - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo -- Add a basic introduction readme ([b240964](https://github.com/NanoForge-dev/Engine/commit/b240964a265b31769a8c5422e23e20156ba56192)) by @MartinFillon -- Add building and dependency docs to every readme ([2d4785b](https://github.com/NanoForge-dev/Engine/commit/2d4785bdcb455e83337b37540f9ab6b3394c0850)) by @MartinFillon - -## Features - -- **input:** Add input library ([387e97d](https://github.com/NanoForge-dev/Engine/commit/387e97d7c3015a869947af4acecf48e8e1b0e2b8)) by @Exeloo - -## Refactor - -- Change test engine (#126) ([ce2c71f](https://github.com/NanoForge-dev/Engine/commit/ce2c71fc1d1b5e3fb3ff4e86fd30aa77c969fbe0)) by @Exeloo -- Migrate namespaces to `@nanoforge-dev` and update related imports ([c84c927](https://github.com/NanoForge-dev/Engine/commit/c84c927ead941d914e5a9fd752fd3a5ac969f981)) by @Exeloo -- **libraries:** Implement initialization validation and standardize nullable fields ([8b04575](https://github.com/NanoForge-dev/Engine/commit/8b04575cf7f649a440b8f40ad6114414406b0c1a)) by @Exeloo -- **libs:** Remove `ECSContext` type in favor of `Context` ([b4ea6f1](https://github.com/NanoForge-dev/Engine/commit/b4ea6f1622b4a29cf57b9bfa1b715f56d248806e)) by @Exeloo - diff --git a/packages/input/LICENSE b/packages/input/LICENSE deleted file mode 100644 index 62c6400b..00000000 --- a/packages/input/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright © 2025 NanoForge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/input/src/index.ts b/packages/input/src/index.ts deleted file mode 100644 index 7d7f3d59..00000000 --- a/packages/input/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -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 deleted file mode 100644 index 5be2d238..00000000 --- a/packages/input/src/input-handler.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { InputEnum } from "./input.enum"; -import { - BUTTONS_MASKS, - type DragState, - MOUSE_BUTTON_MAP, - type MouseState, - type WheelState, -} from "./mouse.types"; - -export class InputHandler { - private offset: { x: number; y: number }; - public inputs: Record = {}; - public mouse: MouseState = { - x: 0, - y: 0, - prevX: 0, - prevY: 0, - deltaX: 0, - deltaY: 0, - focus: false, - }; - public wheel: WheelState = { - deltaX: 0, - deltaY: 0, - deltaZ: 0, - }; - public drag: DragState = { - active: false, - startX: 0, - startY: 0, - x: 0, - y: 0, - deltaX: 0, - deltaY: 0, - }; - - constructor(container: HTMLDivElement) { - this.resetInputs(); - - this.offset = container.getBoundingClientRect(); - - window.addEventListener("keydown", (e: KeyboardEvent) => { - this.inputs[e.code] = true; - }); - - window.addEventListener("keyup", (e: KeyboardEvent) => { - this.inputs[e.code] = false; - }); - - container.addEventListener("mousedown", (e: MouseEvent) => { - const button = MOUSE_BUTTON_MAP[e.button]; - if (button === undefined) return; - - this.inputs[button] = true; - this.updatePointer(e); - - this.drag.active = true; - this.drag.button = button; - this.drag.startX = e.clientX - this.offset.x; - this.drag.startY = e.clientY - this.offset.y; - this.drag.x = e.clientX - this.offset.x; - this.drag.y = e.clientY - this.offset.y; - this.drag.deltaX = 0; - this.drag.deltaY = 0; - }); - - container.addEventListener("mouseup", (e: MouseEvent) => { - const button = MOUSE_BUTTON_MAP[e.button]; - if (button !== undefined) this.inputs[button] = false; - - this.updatePointer(e); - - if (this.drag.button === button) { - this.drag.active = false; - this.drag.button = undefined; - this.drag.x = 0; - this.drag.y = 0; - this.drag.deltaX = 0; - this.drag.deltaY = 0; - } - }); - - container.addEventListener("mousemove", (e: MouseEvent) => { - this.updatePointer(e); - this.updateInputsMouseButtons(e.buttons); - - if (this.drag.active) { - this.drag.x = e.clientX - this.offset.x; - this.drag.y = e.clientY - this.offset.y; - this.drag.deltaX = e.clientX - this.drag.startX - this.offset.x; - this.drag.deltaY = e.clientY - this.drag.startY - this.offset.y; - } - }); - - container.addEventListener("wheel", (e: WheelEvent) => { - this.wheel.deltaX += e.deltaX; - this.wheel.deltaY += e.deltaY; - this.wheel.deltaZ += e.deltaZ; - }); - - container.addEventListener("mouseenter", () => { - this.mouse.focus = true; - }); - - container.addEventListener("mouseleave", () => { - this.mouse.focus = false; - }); - - container.addEventListener("blur", () => { - this.resetInputs(); - }); - - container.addEventListener("visibilitychange", () => { - if (document.hidden) this.resetInputs(); - }); - - for (const key in InputEnum) { - this.inputs[key] = false; - } - } - - public getKeyStatus(key: InputEnum): boolean { - return this.inputs[key] || false; - } - - public getMousePosition() { - return { x: this.mouse.x, y: this.mouse.y }; - } - - public isDragging(button?: InputEnum): boolean { - if (!button) return this.drag.active; - return this.drag.active && this.drag.button === button; - } - - public resetPerFrame(): void { - this.mouse.deltaX = 0; - this.mouse.deltaY = 0; - this.wheel.deltaX = 0; - this.wheel.deltaY = 0; - this.wheel.deltaZ = 0; - } - - private updatePointer(e: MouseEvent): void { - this.mouse.prevX = this.mouse.x; - this.mouse.prevY = this.mouse.y; - this.mouse.x = e.clientX - this.offset.x; - this.mouse.y = e.clientY - this.offset.y; - this.mouse.deltaX = this.mouse.x - this.mouse.prevX; - this.mouse.deltaY = this.mouse.y - this.mouse.prevY; - } - - private updateInputsMouseButtons(buttons: number): void { - for (const [mask, input] of BUTTONS_MASKS) { - this.inputs[input] = (buttons & mask) !== 0; - } - } - - private resetInputs(): void { - for (const key of Object.values(InputEnum)) { - this.inputs[key] = false; - } - - this.drag.active = false; - this.drag.button = undefined; - this.drag.startX = 0; - this.drag.startY = 0; - this.drag.x = 0; - this.drag.y = 0; - this.drag.deltaX = 0; - this.drag.deltaY = 0; - - this.wheel.deltaX = 0; - this.wheel.deltaY = 0; - this.wheel.deltaZ = 0; - - this.mouse.deltaX = 0; - this.mouse.deltaY = 0; - this.mouse.focus = false; - } -} diff --git a/packages/input/src/input.library.ts b/packages/input/src/input.library.ts deleted file mode 100644 index dd2f4b91..00000000 --- a/packages/input/src/input.library.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { BaseInputLibrary, GRAPHICS_LIBRARY, type InitContext } from "@nanoforge-dev/common"; - -import { InputHandler } from "./input-handler"; -import { type InputEnum } from "./input.enum"; -import { type DragState, type MouseState, type WheelState } from "./mouse.types"; - -/** - * Built-in input library. - * - * @remarks - * Listens to browser `keydown`, `keyup`, `mousedown`, `mouseup`, `mousemove`, - * and `wheel` events and exposes a per-frame snapshot of the current input - * state. Must be registered after the graphics library because it uses - * `runAfter: [GRAPHICS_LIBRARY]`. - * - * Register with the application: - * ```ts - * client.useInput(new InputLibrary()); - * ``` - * - * Access in a system's `__run` hook: - * ```ts - * const input = ctx.libraries.getInput().library; - * if (input.isKeyPressed(InputEnum.Space)) player.jump(); - * ``` - */ -export class InputLibrary extends BaseInputLibrary { - private _inputHandler?: InputHandler; - - constructor() { - super({ runAfter: [GRAPHICS_LIBRARY] }); - } - - /** @internal */ - get __name(): string { - return "InputLibrary"; - } - - /** @internal */ - public override async __init(context: InitContext): Promise { - if (!context.container) - throw new Error( - "Input library must be registered on client side (InitContext must contain a container element)", - ); - this._inputHandler = new InputHandler(context.container); - } - - /** @internal */ - public override async __run() { - if (!this._inputHandler) this.throwNotInitializedError(); - this._inputHandler.resetPerFrame(); - } - - /** - * Return whether a key or mouse button is currently held down. - * - * @param key - The key or button to query (see InputEnum). - * @returns `true` when the key is pressed, `false` when released, - * `undefined` when the key has never been seen. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public isKeyPressed(key: InputEnum): boolean | undefined { - if (!this._inputHandler) this.throwNotInitializedError(); - return this._inputHandler.getKeyStatus(key); - } - - /** - * Return a list of all keys and mouse buttons that are currently pressed. - * - * @returns Array of `InputEnum` values for all currently-down inputs. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public getPressedKeys(): InputEnum[] { - if (!this._inputHandler) this.throwNotInitializedError(); - 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; - } - - /** - * Return the current mouse cursor position. - * - * @returns Object with `x` and `y` in CSS pixels. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public getMousePosition(): { x: number; y: number } { - if (!this._inputHandler) this.throwNotInitializedError(); - return this._inputHandler.getMousePosition(); - } - - /** - * Return the full mouse state snapshot for the current frame. - * - * @returns `MouseState` containing position, previous position, deltas, and focus. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public getMouseState(): MouseState { - if (!this._inputHandler) this.throwNotInitializedError(); - return this._inputHandler.mouse; - } - - /** - * Return whether a drag operation is in progress. - * - * @param button - If provided, only returns true when a drag was started - * with this specific button. - * @returns `true` when a drag is active (optionally matching the given button). - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public isDragging(button?: InputEnum): boolean { - if (!this._inputHandler) this.throwNotInitializedError(); - return this._inputHandler.isDragging(button); - } - - /** - * Return the current drag state. - * - * @returns `DragState` with start position, current position, and deltas. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public getDragState(): DragState { - if (!this._inputHandler) this.throwNotInitializedError(); - return this._inputHandler.drag; - } - - /** - * Return the scroll-wheel state accumulated during the current frame. - * - * @remarks - * All deltas are reset to `0` at the start of the next frame. - * - * @returns `WheelState` with `deltaX`, `deltaY`, and `deltaZ`. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public getWheelState(): WheelState { - if (!this._inputHandler) this.throwNotInitializedError(); - return this._inputHandler.wheel; - } -} diff --git a/packages/input/test/input.library.spec.ts b/packages/input/test/input.library.spec.ts deleted file mode 100644 index 6897e9c2..00000000 --- a/packages/input/test/input.library.spec.ts +++ /dev/null @@ -1,327 +0,0 @@ -import { type IConfigRegistry, InitContext } from "@nanoforge-dev/common"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; - -import { EditableApplicationContext } from "../../core/src/common/context/contexts/application.editable-context"; -import { EditableLibraryManager } from "../../core/src/common/library/manager/library.manager"; -import { InputEnum, InputLibrary } from "../src"; - -type MockInputEvent = { - code?: string; - button?: number; - buttons?: number; - clientX?: number; - clientY?: number; - deltaX?: number; - deltaY?: number; - deltaZ?: number; -}; - -const makeEventTargetMock = () => { - const listeners: Record void)[]> = {}; - return { - addEventListener: vi.fn((event: string, handler: (e: MockInputEvent) => void) => { - if (!listeners[event]) listeners[event] = []; - listeners[event].push(handler); - }), - dispatch: (event: string, e: Partial) => { - listeners[event]?.forEach((h) => h(e as MockInputEvent)); - }, - }; -}; - -const makeContext = (container: HTMLDivElement | null) => { - const libraryManager = new EditableLibraryManager(); - const appContext = new EditableApplicationContext(libraryManager); - const configRegistry = {} as IConfigRegistry; - return new InitContext(appContext, libraryManager, configRegistry, { - // @ts-ignore - container, - files: new Map(), - }); -}; - -describe("InputLibrary", () => { - let windowMock: ReturnType & { - getBoundingClientRect: () => { x: number; y: number }; - }; - let documentMock: ReturnType & { - hidden: boolean; - }; - - beforeEach(() => { - windowMock = { ...makeEventTargetMock(), getBoundingClientRect: () => ({ x: 0, y: 0 }) }; - documentMock = { - ...makeEventTargetMock(), - - hidden: false, - }; - - vi.stubGlobal("window", windowMock); - vi.stubGlobal("document", documentMock); - }); - - afterEach(() => { - vi.unstubAllGlobals(); - }); - - describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new InputLibrary().__name).toBe("InputLibrary"); - }); - }); - - describe("before initialization", () => { - it("should throw when methods are called before __init", () => { - const library = new InputLibrary(); - expect(() => library.isKeyPressed(InputEnum.KeyA)).toThrow(); - expect(() => library.getPressedKeys()).toThrow(); - expect(() => library.getMousePosition()).toThrow(); - expect(() => library.getMouseState()).toThrow(); - expect(() => library.isDragging()).toThrow(); - expect(() => library.getDragState()).toThrow(); - expect(() => library.getWheelState()).toThrow(); - }); - - it("should throw when __run is called before __init", async () => { - const library = new InputLibrary(); - - await expect(library.__run()).rejects.toThrow(); - }); - }); - - describe("after initialization", () => { - let library: InputLibrary; - - beforeEach(async () => { - library = new InputLibrary(); - console.log(window); - await library.__init(makeContext(window as unknown as HTMLDivElement)); - }); - - it("should register all expected event listeners", () => { - expect(windowMock.addEventListener).toHaveBeenCalledWith("keydown", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("keyup", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("mousedown", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("mouseup", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("mousemove", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("wheel", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("mouseenter", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("mouseleave", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith("blur", expect.any(Function)); - expect(windowMock.addEventListener).toHaveBeenCalledWith( - "visibilitychange", - expect.any(Function), - ); - }); - - it("should return false for any key before any key event", () => { - expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); - expect(library.isKeyPressed(InputEnum.Space)).toBe(false); - expect(library.isKeyPressed(InputEnum.Enter)).toBe(false); - }); - - it("should return an empty pressed keys list when no key is down", () => { - expect(library.getPressedKeys()).toStrictEqual([]); - }); - - it("should return true for a key after a keydown event", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - expect(library.isKeyPressed(InputEnum.KeyA)).toBe(true); - }); - - it("should return false for a key after keydown then keyup", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - windowMock.dispatch("keyup", { code: InputEnum.KeyA }); - expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); - }); - - it("should list all currently pressed keys", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - windowMock.dispatch("keydown", { code: InputEnum.Space }); - const pressed = library.getPressedKeys(); - expect(pressed).toContain(InputEnum.KeyA); - expect(pressed).toContain(InputEnum.Space); - expect(pressed.length).toBe(2); - }); - - it("should remove a released key from pressed keys", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - windowMock.dispatch("keydown", { code: InputEnum.Space }); - windowMock.dispatch("keyup", { code: InputEnum.KeyA }); - const pressed = library.getPressedKeys(); - expect(pressed).not.toContain(InputEnum.KeyA); - expect(pressed).toContain(InputEnum.Space); - }); - - it("should handle mouse button press and release", () => { - windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); - expect(library.isKeyPressed(InputEnum.MouseLeft)).toBe(true); - - windowMock.dispatch("mouseup", { button: 0, clientX: 10, clientY: 20 }); - expect(library.isKeyPressed(InputEnum.MouseLeft)).toBe(false); - }); - - it("should handle unknown mouse input", () => { - windowMock.dispatch("mousedown", { button: -2 }); - windowMock.dispatch("mousedown", { button: 999 }); - windowMock.dispatch("mouseup", { button: 999 }); - - const pressed = library.getPressedKeys(); - - expect(pressed).toHaveLength(0); - }); - - it("should update mouse position and state on move", () => { - windowMock.dispatch("mousemove", { clientX: 100, clientY: 200, buttons: 0 }); - - expect(library.getMousePosition()).toStrictEqual({ x: 100, y: 200 }); - expect(library.getMouseState()).toMatchObject({ - x: 100, - y: 200, - deltaX: 100, - deltaY: 200, - }); - }); - - it("should start, update and stop dragging", () => { - windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); - expect(library.isDragging()).toBe(true); - expect(library.isDragging(InputEnum.MouseLeft)).toBe(true); - - windowMock.dispatch("mousemove", { clientX: 25, clientY: 45, buttons: 1 }); - expect(library.getDragState()).toMatchObject({ - active: true, - startX: 10, - startY: 20, - x: 25, - y: 45, - deltaX: 15, - deltaY: 25, - }); - - windowMock.dispatch("mouseup", { button: 0, clientX: 25, clientY: 45 }); - expect(library.isDragging()).toBe(false); - expect(library.getDragState()).toMatchObject({ - active: false, - deltaX: 0, - deltaY: 0, - }); - }); - - it("should accumulate wheel delta", () => { - windowMock.dispatch("wheel", { deltaX: 1, deltaY: 2, deltaZ: 3 }); - windowMock.dispatch("wheel", { deltaX: 4, deltaY: 5, deltaZ: 6 }); - - expect(library.getWheelState()).toStrictEqual({ - deltaX: 5, - deltaY: 7, - deltaZ: 9, - }); - }); - - it("should reset per frame on __run", async () => { - windowMock.dispatch("mousemove", { clientX: 10, clientY: 20, buttons: 0 }); - windowMock.dispatch("wheel", { deltaX: 1, deltaY: 2, deltaZ: 3 }); - - await library.__run(); - - expect(library.getMouseState()).toMatchObject({ - deltaX: 0, - deltaY: 0, - }); - expect(library.getWheelState()).toStrictEqual({ - deltaX: 0, - deltaY: 0, - deltaZ: 0, - }); - }); - - it("should reset inputs on blur", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); - windowMock.dispatch("wheel", { deltaX: 1, deltaY: 2, deltaZ: 3 }); - - windowMock.dispatch("blur", {}); - - expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); - expect(library.isKeyPressed(InputEnum.MouseLeft)).toBe(false); - expect(library.isDragging()).toBe(false); - expect(library.getWheelState()).toStrictEqual({ - deltaX: 0, - deltaY: 0, - deltaZ: 0, - }); - }); - - it("should reset inputs when document becomes hidden", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - documentMock.hidden = true; - - windowMock.dispatch("visibilitychange", {}); - - expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); - }); - - it("should update pointer focus on mouse enter and leave", () => { - windowMock.dispatch("mouseenter", {}); - expect(library.getMouseState().focus).toBe(true); - - windowMock.dispatch("mouseleave", {}); - expect(library.getMouseState().focus).toBe(false); - }); - - it("should fully reset drag state when the released button matches the active drag button", () => { - windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); - windowMock.dispatch("mousemove", { clientX: 30, clientY: 50, buttons: 1 }); - - expect(library.getDragState()).toMatchObject({ - active: true, - button: InputEnum.MouseLeft, - x: 30, - y: 50, - deltaX: 20, - deltaY: 30, - }); - - windowMock.dispatch("mouseup", { button: 0, clientX: 30, clientY: 50 }); - - expect(library.getDragState()).toMatchObject({ - active: false, - button: undefined, - x: 0, - y: 0, - deltaX: 0, - deltaY: 0, - }); - }); - - it("should not reset inputs when visibility changes but document is not hidden", () => { - windowMock.dispatch("keydown", { code: InputEnum.KeyA }); - documentMock.hidden = false; - - documentMock.dispatch("visibilitychange", {}); - - expect(library.isKeyPressed(InputEnum.KeyA)).toBe(true); - }); - - it("should keep drag active when mouseup button does not match active drag button", () => { - windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); - - expect(library.getDragState()).toMatchObject({ - active: true, - button: InputEnum.MouseLeft, - startX: 10, - startY: 20, - }); - - windowMock.dispatch("mouseup", { button: 2, clientX: 15, clientY: 25 }); - - expect(library.getDragState()).toMatchObject({ - active: true, - button: InputEnum.MouseLeft, - startX: 10, - startY: 20, - }); - }); - }); -}); diff --git a/packages/input/tsdown.config.ts b/packages/input/tsdown.config.ts deleted file mode 100644 index 12f5dea6..00000000 --- a/packages/input/tsdown.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createTsdownConfig } from "../../tsdown.config"; - -export default [createTsdownConfig()]; diff --git a/packages/music/.nvmrc b/packages/music/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/music/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/music/CHANGELOG.md b/packages/music/CHANGELOG.md deleted file mode 100644 index 68d930e6..00000000 --- a/packages/music/CHANGELOG.md +++ /dev/null @@ -1,62 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/music@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/music@1.0.1...@nanoforge-dev/music@1.3.0) - (2026-05-26) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/music@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/music@1.0.0...@nanoforge-dev/music@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/music@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/music@1.0.0) - (2026-01-09) - -## Bug Fixes - -- **music:** Versions issue ([7304293](https://github.com/NanoForge-dev/Engine/commit/7304293efbcc2a2ae82fbc82278390b63ff33c01)) by @MartinFillon - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo -- Add a basic introduction readme ([b240964](https://github.com/NanoForge-dev/Engine/commit/b240964a265b31769a8c5422e23e20156ba56192)) by @MartinFillon -- Add building and dependency docs to every readme ([2d4785b](https://github.com/NanoForge-dev/Engine/commit/2d4785bdcb455e83337b37540f9ab6b3394c0850)) by @MartinFillon - -## Features - -- **music:** Finish music library and add an interface for mutable libraries ([8e00c5d](https://github.com/NanoForge-dev/Engine/commit/8e00c5d00f2901ada86f59667eff7e5d3446076b)) by @MartinFillon -- **music:** Init basic music library ([de447e2](https://github.com/NanoForge-dev/Engine/commit/de447e2f64ad166fc26e9da9dd987479bf17f67c)) by @MartinFillon - -## Refactor - -- Change test engine (#126) ([ce2c71f](https://github.com/NanoForge-dev/Engine/commit/ce2c71fc1d1b5e3fb3ff4e86fd30aa77c969fbe0)) by @Exeloo -- Migrate namespaces to `@nanoforge-dev` and update related imports ([c84c927](https://github.com/NanoForge-dev/Engine/commit/c84c927ead941d914e5a9fd752fd3a5ac969f981)) by @Exeloo -- **libraries:** Implement initialization validation and standardize nullable fields ([8b04575](https://github.com/NanoForge-dev/Engine/commit/8b04575cf7f649a440b8f40ad6114414406b0c1a)) by @Exeloo -- **libs:** Remove `ECSContext` type in favor of `Context` ([b4ea6f1](https://github.com/NanoForge-dev/Engine/commit/b4ea6f1622b4a29cf57b9bfa1b715f56d248806e)) by @Exeloo - diff --git a/packages/music/LICENSE b/packages/music/LICENSE deleted file mode 100644 index 62c6400b..00000000 --- a/packages/music/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright © 2025 NanoForge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/music/cliff.toml b/packages/music/cliff.toml deleted file mode 100644 index 5163767e..00000000 --- a/packages/music/cliff.toml +++ /dev/null @@ -1,79 +0,0 @@ -[changelog] -header = """ -# Changelog - -All notable changes to this project will be documented in this file.\n -""" -body = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -{% if version %}\ - # [{{ version | trim_start_matches(pat="v") }}]\ - {% if previous %}\ - {% if previous.version %}\ - ({{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }})\ - {% else %}\ - ({{ self::remote_url() }}/tree/{{ version }})\ - {% endif %}\ - {% endif %} \ - - ({{ timestamp | date(format="%Y-%m-%d") }}) -{% else %}\ - # [unreleased] -{% endif %}\ -{% for group, commits in commits | group_by(attribute="group") %} - ## {{ group | upper_first }} - {% for commit in commits %} - - {% if commit.scope %}\ - **{{commit.scope}}:** \ - {% endif %}\ - {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ - {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ - {% if commit.breaking %}\ - {% for footer in commit.footers %}\ - {% if footer.breaking %}\ - \n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\ - {% endif %}\ - {% endfor %}\ - {% endif %}\ - {% endfor %} -{% endfor %}\ -{% if github.contributors | filter(attribute="is_first_time", value=true) | length %}\ - \n### New Contributors\n - {% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}\ - - @{{ contributor.username }} made their first contribution in #{{ contributor.pr_number }} - {% endfor %}\ -{% endif %}\n -""" -trim = true -footer = "" - -[git] -conventional_commits = true -filter_unconventional = true -commit_parsers = [ - { message = "^feat", group = "Features"}, - { message = "^fix", group = "Bug Fixes"}, - { message = "^docs", group = "Documentation"}, - { message = "^perf", group = "Performance"}, - { message = "^refactor", group = "Refactor"}, - { message = "^types", group = "Typings"}, - { message = ".*deprecated", body = ".*deprecated", group = "Deprecation"}, - { message = "^revert", skip = true}, - { message = "^style", group = "Styling"}, - { message = "^test", group = "Testing"}, - { message = "^chore", skip = true}, - { message = "^ci", skip = true}, - { message = "^build", skip = true}, - { body = ".*security", group = "Security"}, -] -filter_commits = true -protect_breaking_commits = true -tag_pattern = "^[0-9]+" -ignore_tags = "" -topo_order = false -sort_commits = "newest" - -[remote.github] -owner = "NanoForge-dev" -repo = "Engine" diff --git a/packages/music/src/index.ts b/packages/music/src/index.ts deleted file mode 100644 index dbfecc27..00000000 --- a/packages/music/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { MusicLibrary } from "./music.library"; diff --git a/packages/music/src/music.library.ts b/packages/music/src/music.library.ts deleted file mode 100644 index 1a9b904e..00000000 --- a/packages/music/src/music.library.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { BaseMusicLibrary, NfNotFound } from "@nanoforge-dev/common"; - -/** - * Built-in music library. - * - * @remarks - * Manages a collection of named `HTMLAudioElement` instances and ensures only - * one track plays at a time. Load tracks with `load` and start - * playback with `play`. Register with the application: - * - * ```ts - * client.use(MUSIC_LIBRARY, new MusicLibrary()); - * ``` - * - * Access in game code: - * ```ts - * const music = ctx.libraries.getMusic().library; - * music.load("theme", "/music/main-theme.mp3"); - * music.play("theme"); - * ``` - */ -export class MusicLibrary extends BaseMusicLibrary { - private muted: boolean = true; - private musics?: Map; - private current: HTMLAudioElement | null = null; - - /** @internal */ - get __name(): string { - return "NfMusic"; - } - - /** @internal */ - public async __init(): Promise { - this.musics = new Map(); - this.muted = true; - } - - /** - * Toggle the muted state of all loaded music tracks. - * - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public mute(): void { - if (!this.musics) this.throwNotInitializedError(); - this.muted = !this.muted; - for (const [, element] of this.musics) { - if (element) { - element.muted = this.muted; - } - } - } - - /** - * Stop the currently playing track and start the requested one. - * - * @param music - Key that identifies the track (as passed to load). - * @throws `NfNotFound` When no track is registered under the given key. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public play(music: string): void { - if (!this.musics) this.throwNotInitializedError(); - const musicElement = this.musics.get(music); - - if (musicElement) { - this.current?.pause(); - this.current = musicElement; - this.current - ?.play() - .then(() => {}) - .catch((e) => { - console.error(`Got error: ${e}`); - }); - } else { - this.current = null; - throw new NfNotFound(music); - } - } - - /** - * Register a music track under a unique key. - * - * @remarks - * Creates an `HTMLAudioElement` from the provided URL. The track respects - * the current muted state at load time. - * - * @param music - Unique key used to reference this track (e.g. "theme"). - * @param file - URL or path to the audio file. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public load(music: string, file: string) { - if (!this.musics) this.throwNotInitializedError(); - const element = new Audio(file); - if (element) { - element.muted = this.muted; - } - this.musics.set(music, element); - } -} diff --git a/packages/music/tsdoc.json b/packages/music/tsdoc.json deleted file mode 100644 index ae9ae564..00000000 --- a/packages/music/tsdoc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"], - "tagDefinitions": [ - { - "tagName": "@default", - "syntaxKind": "block", - "allowMultiple": false - } - ], - "supportForTags": { - "@default": true - } -} diff --git a/packages/music/tsdown.config.ts b/packages/music/tsdown.config.ts deleted file mode 100644 index 12f5dea6..00000000 --- a/packages/music/tsdown.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createTsdownConfig } from "../../tsdown.config"; - -export default [createTsdownConfig()]; diff --git a/packages/network-client/.cliff-jumperrc.json b/packages/network-client/.cliff-jumperrc.json deleted file mode 100644 index bba31587..00000000 --- a/packages/network-client/.cliff-jumperrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "network-client", - "org": "nanoforge-dev", - "packagePath": "packages/network-client", - "tagTemplate": "{{new-version}}", - "identifierBase": false -} diff --git a/packages/network-client/.nvmrc b/packages/network-client/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/network-client/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/network-client/CHANGELOG.md b/packages/network-client/CHANGELOG.md deleted file mode 100644 index c9ee867c..00000000 --- a/packages/network-client/CHANGELOG.md +++ /dev/null @@ -1,64 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -## Bug Fixes - -- Change url protocols validation on isIpOrURL validator in network (#398) ([541dd16](https://github.com/NanoForge-dev/Engine/commit/541dd16e307e355288ec49ec7ae75566bb7fe2b5)) by @Exeloo - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -## Bug Fixes - -- Change check for address from fqdn to url (#394) ([8823c59](https://github.com/NanoForge-dev/Engine/commit/8823c5911f8c5a673a96c32df9888b2dea4d6370)) by @Exeloo - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -## Features - -- Add drag and drop on graphics (#380) ([afffa7a](https://github.com/NanoForge-dev/Engine/commit/afffa7afd1f51eba2d2cd0d96fe47e5db04ac534)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/network-client@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-client@1.2.0...@nanoforge-dev/network-client@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/network-client@1.2.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-client@1.1.0...@nanoforge-dev/network-client@1.2.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- Add loader given env to config registry (#246) ([dce12b7](https://github.com/NanoForge-dev/Engine/commit/dce12b7601b613e850987da1e0766634a821bdfc)) by @Exeloo - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/network-client@1.1.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-client@1.0.1...@nanoforge-dev/network-client@1.1.0) - (2026-02-20) - -## Features - -- **network:** Setup ssl and wssl (#228) ([c52b623](https://github.com/NanoForge-dev/Engine/commit/c52b623118890ddbc6b49335af485d3d4c44bce3)) by @MartinFillon - -# [@nanoforge-dev/network-client@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-client@1.0.0...@nanoforge-dev/network-client@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/network-client@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/network-client@1.0.0) - (2026-01-09) - -## Features - -- **packages/network:** Client and server for tcp/udp and networked pong as example (#156) ([839fb95](https://github.com/NanoForge-dev/Engine/commit/839fb95449f6ae0ee66d7f7e279374268b743f65)) by @Tchips46 - diff --git a/packages/network-client/LICENSE b/packages/network-client/LICENSE deleted file mode 100644 index 62c6400b..00000000 --- a/packages/network-client/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright © 2025 NanoForge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/network-client/README.md b/packages/network-client/README.md deleted file mode 100644 index 4c5ee072..00000000 --- a/packages/network-client/README.md +++ /dev/null @@ -1,97 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/network-client` is a network lib with tcp and udp support for client-side usage. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/network-client -yarn add @nanoforge-dev/network-client -pnpm add @nanoforge-dev/network-client -bun add @nanoforge-dev/network-client -``` - -## Example usage - -Initilize the library in your main file. - -```ts -import { type IRunClientOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { NetworkClientLibrary } from "@nanoforge-dev/network-client"; - -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const network = new NetworkClientLibrary(); - - app.useNetwork(network); - - await app.init(options); - - await app.run(); -} -``` - -Use to receive packets - -```ts -export function myReceiveSystem(registry: Registry, ctx: Context) { - const network = ctx.libs.getNetwork(); - - network.tcp.getReceivedPackets().forEach((packet) => { - const data = JSON.parse(new TextDecoder().decode(packet)); - // Do something with the data - }); -} -``` - -Use to send packets - -```ts -export function mySendSystem(registry: Registry, ctx: Context) { - const network = ctx.libs.getNetwork(); - - // Do something to get a data - const packet = new TextEncoder().encode(JSON.stringify(data)); - network.tcp.sendPacket(packet); -} -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/network-client -[npm]: https://www.npmjs.com/package/@nanoforge-dev/network-client -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/network-client/cliff.toml b/packages/network-client/cliff.toml deleted file mode 100644 index 5163767e..00000000 --- a/packages/network-client/cliff.toml +++ /dev/null @@ -1,79 +0,0 @@ -[changelog] -header = """ -# Changelog - -All notable changes to this project will be documented in this file.\n -""" -body = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -{% if version %}\ - # [{{ version | trim_start_matches(pat="v") }}]\ - {% if previous %}\ - {% if previous.version %}\ - ({{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }})\ - {% else %}\ - ({{ self::remote_url() }}/tree/{{ version }})\ - {% endif %}\ - {% endif %} \ - - ({{ timestamp | date(format="%Y-%m-%d") }}) -{% else %}\ - # [unreleased] -{% endif %}\ -{% for group, commits in commits | group_by(attribute="group") %} - ## {{ group | upper_first }} - {% for commit in commits %} - - {% if commit.scope %}\ - **{{commit.scope}}:** \ - {% endif %}\ - {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ - {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ - {% if commit.breaking %}\ - {% for footer in commit.footers %}\ - {% if footer.breaking %}\ - \n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\ - {% endif %}\ - {% endfor %}\ - {% endif %}\ - {% endfor %} -{% endfor %}\ -{% if github.contributors | filter(attribute="is_first_time", value=true) | length %}\ - \n### New Contributors\n - {% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}\ - - @{{ contributor.username }} made their first contribution in #{{ contributor.pr_number }} - {% endfor %}\ -{% endif %}\n -""" -trim = true -footer = "" - -[git] -conventional_commits = true -filter_unconventional = true -commit_parsers = [ - { message = "^feat", group = "Features"}, - { message = "^fix", group = "Bug Fixes"}, - { message = "^docs", group = "Documentation"}, - { message = "^perf", group = "Performance"}, - { message = "^refactor", group = "Refactor"}, - { message = "^types", group = "Typings"}, - { message = ".*deprecated", body = ".*deprecated", group = "Deprecation"}, - { message = "^revert", skip = true}, - { message = "^style", group = "Styling"}, - { message = "^test", group = "Testing"}, - { message = "^chore", skip = true}, - { message = "^ci", skip = true}, - { message = "^build", skip = true}, - { body = ".*security", group = "Security"}, -] -filter_commits = true -protect_breaking_commits = true -tag_pattern = "^[0-9]+" -ignore_tags = "" -topo_order = false -sort_commits = "newest" - -[remote.github] -owner = "NanoForge-dev" -repo = "Engine" diff --git a/packages/network-client/mint-tsdocs.config.json b/packages/network-client/mint-tsdocs.config.json deleted file mode 100644 index f2b37a87..00000000 --- a/packages/network-client/mint-tsdocs.config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/network-client", - "lint": { - "eslint": { - "enabled": true - } - }, - "templates": { - "userTemplateDir": "../../docs/templates" - } -} diff --git a/packages/network-client/prettier.config.js b/packages/network-client/prettier.config.js deleted file mode 100644 index 27d0e269..00000000 --- a/packages/network-client/prettier.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-prettier-config"; - -export default config; diff --git a/packages/network-client/src/client.network.library.ts b/packages/network-client/src/client.network.library.ts deleted file mode 100644 index a3fade86..00000000 --- a/packages/network-client/src/client.network.library.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { BaseNetworkLibrary, type InitContext, NfConfigException } from "@nanoforge-dev/common"; - -import { ClientConfigNetwork } from "./config.client.network"; -import { TCPClient } from "./tcp.client.network"; -import { UDPClient } from "./udp.client.network"; - -/** - * Built-in network library for client-side applications. - * - * @remarks - * Reads network configuration from the environment via - * `ClientConfigNetwork` and automatically connects to the server over - * TCP (WebSocket), UDP (WebRTC data channel), or both. Register with: - * - * ```ts - * client.useNetwork(new NetworkClientLibrary()); - * ``` - * - * Configuration (via environment variables): - * - `SERVER_ADDRESS` — hostname or IP of the server (required). - * - `SERVER_TCP_PORT` — WebSocket port for TCP (optional). - * - `SERVER_UDP_PORT` — signaling port for UDP/WebRTC (optional). - * - `MAGIC_VALUE` — packet framing delimiter (default: `"PACKET_END"`). - * - `WSS` — set to `"true"` to use `wss://` / `https://` (default: `false`). - * - * After `init`, access the connections via `tcp` and `udp`. - */ -export class NetworkClientLibrary extends BaseNetworkLibrary { - /** - * Reliable, ordered WebSocket-based connection to the server. - * - * @remarks - * Only available when `SERVER_TCP_PORT` was specified in the environment. - */ - public tcp!: TCPClient; - - /** - * Unreliable, unordered WebRTC data-channel connection to the server. - * - * @remarks - * Only available when `SERVER_UDP_PORT` was specified in the environment. - */ - public udp!: UDPClient; - - /** @internal */ - get __name(): string { - return "NetworkClientLibrary"; - } - - /** @internal */ - public override async __init(context: InitContext): Promise { - const config: ClientConfigNetwork = await context.config.registerConfig(ClientConfigNetwork); - - if (config.SERVER_TCP_PORT === undefined && config.SERVER_UDP_PORT === undefined) { - throw new NfConfigException("No server port specified to connect", this.__name); - } - - if (config.SERVER_TCP_PORT !== undefined) { - this.tcp = new TCPClient( - +config.SERVER_TCP_PORT, - config.SERVER_ADDRESS, - config.MAGIC_VALUE, - config.WSS, - ); - await this.tcp.connect(); - } - - if (config.SERVER_UDP_PORT !== undefined) { - this.udp = new UDPClient( - +config.SERVER_UDP_PORT, - config.SERVER_ADDRESS, - config.MAGIC_VALUE, - config.WSS, - ); - await this.udp.connect(); - } - } -} diff --git a/packages/network-client/tsconfig.json b/packages/network-client/tsconfig.json deleted file mode 100644 index 1ada333c..00000000 --- a/packages/network-client/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig.json", - "extends": "../../tsconfig.json", - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist"], - "compilerOptions": { - "declaration": true, - "paths": { - "/snippets/*": ["./docs/snippets/*"] - } - }, - "mdx": { - "checkMdx": true - } -} diff --git a/packages/network-client/tsdoc.json b/packages/network-client/tsdoc.json deleted file mode 100644 index ae9ae564..00000000 --- a/packages/network-client/tsdoc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"], - "tagDefinitions": [ - { - "tagName": "@default", - "syntaxKind": "block", - "allowMultiple": false - } - ], - "supportForTags": { - "@default": true - } -} diff --git a/packages/network-client/tsdown.config.ts b/packages/network-client/tsdown.config.ts deleted file mode 100644 index 12f5dea6..00000000 --- a/packages/network-client/tsdown.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createTsdownConfig } from "../../tsdown.config"; - -export default [createTsdownConfig()]; diff --git a/packages/network-server/.cliff-jumperrc.json b/packages/network-server/.cliff-jumperrc.json deleted file mode 100644 index 48ea206e..00000000 --- a/packages/network-server/.cliff-jumperrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "network-server", - "org": "nanoforge-dev", - "packagePath": "packages/network-server", - "tagTemplate": "{{new-version}}", - "identifierBase": false -} diff --git a/packages/network-server/.nvmrc b/packages/network-server/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/network-server/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/network-server/CHANGELOG.md b/packages/network-server/CHANGELOG.md deleted file mode 100644 index 5cb0595d..00000000 --- a/packages/network-server/CHANGELOG.md +++ /dev/null @@ -1,60 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -## Bug Fixes - -- Change check for address from fqdn to url (#394) ([8823c59](https://github.com/NanoForge-dev/Engine/commit/8823c5911f8c5a673a96c32df9888b2dea4d6370)) by @Exeloo - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -## Features - -- Add drag and drop on graphics (#380) ([afffa7a](https://github.com/NanoForge-dev/Engine/commit/afffa7afd1f51eba2d2cd0d96fe47e5db04ac534)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/network-server@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-server@1.2.0...@nanoforge-dev/network-server@1.3.0) - (2026-05-26) - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -# [@nanoforge-dev/network-server@1.2.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-server@1.1.0...@nanoforge-dev/network-server@1.2.0) - (2026-04-02) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo -- Add loader given env to config registry (#246) ([dce12b7](https://github.com/NanoForge-dev/Engine/commit/dce12b7601b613e850987da1e0766634a821bdfc)) by @Exeloo - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/network-server@1.1.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-server@1.0.1...@nanoforge-dev/network-server@1.1.0) - (2026-02-20) - -## Features - -- **network:** Setup ssl and wssl (#228) ([c52b623](https://github.com/NanoForge-dev/Engine/commit/c52b623118890ddbc6b49335af485d3d4c44bce3)) by @MartinFillon - -# [@nanoforge-dev/network-server@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/network-server@1.0.0...@nanoforge-dev/network-server@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/network-server@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/network-server@1.0.0) - (2026-01-09) - -## Features - -- **packages/network:** Client and server for tcp/udp and networked pong as example (#156) ([839fb95](https://github.com/NanoForge-dev/Engine/commit/839fb95449f6ae0ee66d7f7e279374268b743f65)) by @Tchips46 - diff --git a/packages/network-server/LICENSE b/packages/network-server/LICENSE deleted file mode 100644 index 62c6400b..00000000 --- a/packages/network-server/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright © 2025 NanoForge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/network-server/README.md b/packages/network-server/README.md deleted file mode 100644 index aeb5b00a..00000000 --- a/packages/network-server/README.md +++ /dev/null @@ -1,99 +0,0 @@ -
-
-

- NanoForge -

-
-

- npm version - npm downloads - Tests status - Last commit - Contributors -

-
- -## About - -`@nanoforge-dev/network-server` is a network lib with tcp and udp support for server-side usage. - -## Installation - -**Node.js 25 or newer is required.** - -```sh -npm install @nanoforge-dev/network-server -yarn add @nanoforge-dev/network-server -pnpm add @nanoforge-dev/network-server -bun add @nanoforge-dev/network-server -``` - -## Example usage - -Initilize the library in your main file. - -```ts -import { type IRunServerOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { NetworkServerLibrary } from "@nanoforge-dev/network-server"; - -export async function main(options: IRunServerOptions) { - const app = NanoforgeFactory.createServer(); - - const network = new NetworkServerLibrary(); - - app.useNetwork(network); - - await app.init(options); - - await app.run(); -} -``` - -Use to receive packets - -```ts -export function myReceiveSystem(registry: Registry, ctx: Context) { - const network = ctx.libs.getNetwork(); - - network.tcp.getReceivedPackets().forEach((packets, client) => { - packets.forEach((packet) => { - const data = JSON.parse(new TextDecoder().decode(packet)); - // Do something with the data - }); - }); -} -``` - -Use to send packets to everyones - -```ts -export function mySendSystem(registry: Registry, ctx: Context) { - const network = ctx.libs.getNetwork(); - - // Do something to get a data - const packet = new TextEncoder().encode(JSON.stringify(data)); - network.tcp.sendToEverybody(packet); -} -``` - -## Links - -- [GitHub][source] -- [npm][npm] - -## Contributing - -Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the -[documentation][documentation]. -See [the contribution guide][contributing] if you'd like to submit a PR. - -## Help - -If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. - -[documentation]: https://github.com/NanoForge-dev/Engine -[discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/network-server -[npm]: https://www.npmjs.com/package/@nanoforge-dev/network-server -[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/network-server/cliff.toml b/packages/network-server/cliff.toml deleted file mode 100644 index 5163767e..00000000 --- a/packages/network-server/cliff.toml +++ /dev/null @@ -1,79 +0,0 @@ -[changelog] -header = """ -# Changelog - -All notable changes to this project will be documented in this file.\n -""" -body = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -{% if version %}\ - # [{{ version | trim_start_matches(pat="v") }}]\ - {% if previous %}\ - {% if previous.version %}\ - ({{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }})\ - {% else %}\ - ({{ self::remote_url() }}/tree/{{ version }})\ - {% endif %}\ - {% endif %} \ - - ({{ timestamp | date(format="%Y-%m-%d") }}) -{% else %}\ - # [unreleased] -{% endif %}\ -{% for group, commits in commits | group_by(attribute="group") %} - ## {{ group | upper_first }} - {% for commit in commits %} - - {% if commit.scope %}\ - **{{commit.scope}}:** \ - {% endif %}\ - {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ - {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ - {% if commit.breaking %}\ - {% for footer in commit.footers %}\ - {% if footer.breaking %}\ - \n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\ - {% endif %}\ - {% endfor %}\ - {% endif %}\ - {% endfor %} -{% endfor %}\ -{% if github.contributors | filter(attribute="is_first_time", value=true) | length %}\ - \n### New Contributors\n - {% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}\ - - @{{ contributor.username }} made their first contribution in #{{ contributor.pr_number }} - {% endfor %}\ -{% endif %}\n -""" -trim = true -footer = "" - -[git] -conventional_commits = true -filter_unconventional = true -commit_parsers = [ - { message = "^feat", group = "Features"}, - { message = "^fix", group = "Bug Fixes"}, - { message = "^docs", group = "Documentation"}, - { message = "^perf", group = "Performance"}, - { message = "^refactor", group = "Refactor"}, - { message = "^types", group = "Typings"}, - { message = ".*deprecated", body = ".*deprecated", group = "Deprecation"}, - { message = "^revert", skip = true}, - { message = "^style", group = "Styling"}, - { message = "^test", group = "Testing"}, - { message = "^chore", skip = true}, - { message = "^ci", skip = true}, - { message = "^build", skip = true}, - { body = ".*security", group = "Security"}, -] -filter_commits = true -protect_breaking_commits = true -tag_pattern = "^[0-9]+" -ignore_tags = "" -topo_order = false -sort_commits = "newest" - -[remote.github] -owner = "NanoForge-dev" -repo = "Engine" diff --git a/packages/network-server/eslint.config.js b/packages/network-server/eslint.config.js deleted file mode 100644 index 62ec06dc..00000000 --- a/packages/network-server/eslint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-eslint-config"; - -export default config; diff --git a/packages/network-server/mint-tsdocs.config.json b/packages/network-server/mint-tsdocs.config.json deleted file mode 100644 index ce8756c1..00000000 --- a/packages/network-server/mint-tsdocs.config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/network-server", - "lint": { - "eslint": { - "enabled": true - } - }, - "templates": { - "userTemplateDir": "../../docs/templates" - } -} diff --git a/packages/network-server/prettier.config.js b/packages/network-server/prettier.config.js deleted file mode 100644 index 27d0e269..00000000 --- a/packages/network-server/prettier.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-prettier-config"; - -export default config; diff --git a/packages/network-server/src/wrtc.d.ts b/packages/network-server/src/wrtc.d.ts deleted file mode 100644 index 8164eb6c..00000000 --- a/packages/network-server/src/wrtc.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'wrtc'; \ No newline at end of file diff --git a/packages/network-server/tsconfig.json b/packages/network-server/tsconfig.json deleted file mode 100644 index 2690c0ff..00000000 --- a/packages/network-server/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig.json", - "extends": "../../tsconfig.json", - "compilerOptions": { - "types": ["node"], - "declaration": true, - "paths": { - "/snippets/*": ["./docs/snippets/*"] - } - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist"], - "mdx": { - "checkMdx": true - } -} diff --git a/packages/network-server/tsdoc.json b/packages/network-server/tsdoc.json deleted file mode 100644 index ae9ae564..00000000 --- a/packages/network-server/tsdoc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"], - "tagDefinitions": [ - { - "tagName": "@default", - "syntaxKind": "block", - "allowMultiple": false - } - ], - "supportForTags": { - "@default": true - } -} diff --git a/packages/network-server/tsdown.config.ts b/packages/network-server/tsdown.config.ts deleted file mode 100644 index 12f5dea6..00000000 --- a/packages/network-server/tsdown.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createTsdownConfig } from "../../tsdown.config"; - -export default [createTsdownConfig()]; diff --git a/packages/sound/.nvmrc b/packages/sound/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/sound/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/sound/.prettierignore b/packages/sound/.prettierignore deleted file mode 100644 index 64b127c9..00000000 --- a/packages/sound/.prettierignore +++ /dev/null @@ -1,11 +0,0 @@ -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock -bun.lock - -.turbo/ -node_modules/ -dist/ -coverage/ -CHANGELOG.md diff --git a/packages/sound/CHANGELOG.md b/packages/sound/CHANGELOG.md deleted file mode 100644 index ecb5d789..00000000 --- a/packages/sound/CHANGELOG.md +++ /dev/null @@ -1,61 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -# [1.4.2](https://github.com/NanoForge-dev/Engine/compare/1.4.1...1.4.2) - (2026-07-06) - -# [1.4.1](https://github.com/NanoForge-dev/Engine/compare/1.4.0...1.4.1) - (2026-07-06) - -# [1.4.0](https://github.com/NanoForge-dev/Engine/compare/1.3.1...1.4.0) - (2026-07-01) - -## Documentation - -- Add in code docs (#370) ([0146a0e](https://github.com/NanoForge-dev/Engine/commit/0146a0e3e7783c8f3bed9640ad3a452531791e0c)) by @Exeloo - -# [1.3.1](https://github.com/NanoForge-dev/Engine/compare/1.3.0...1.3.1) - (2026-06-04) - -# [@nanoforge-dev/sound@1.3.0](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/sound@1.0.1...@nanoforge-dev/sound@1.3.0) - (2026-05-26) - -## Features - -- Add core editor contribution ressources (#263) ([6c27bf0](https://github.com/NanoForge-dev/Engine/commit/6c27bf08b7d894d96940d2c572e224c01c48e374)) by @Exeloo - -## Refactor - -- **docs:** Migrate to mdx (#343) ([66f66a7](https://github.com/NanoForge-dev/Engine/commit/66f66a71fa0a50cf528645c0929702e973ba6178)) by @MartinFillon - -## Testing - -- Add unit and e2e tests (#244) ([d593579](https://github.com/NanoForge-dev/Engine/commit/d593579f149370e1d4f32eec5cac5d251fc31f9c)) by @Exeloo - -# [@nanoforge-dev/sound@1.0.1](https://github.com/NanoForge-dev/Engine/compare/@nanoforge-dev/sound@1.0.0...@nanoforge-dev/sound@1.0.1) - (2026-02-16) - -## Documentation - -- Setup typedoc (#192) ([fa908e7](https://github.com/NanoForge-dev/Engine/commit/fa908e7e268fa1770be58fc62a0257f3760480b2)) by @MartinFillon -- Fix readme badges (#186) ([fd8d93d](https://github.com/NanoForge-dev/Engine/commit/fd8d93d13a0fbad95ef9952acd10faad9e112c78)) by @Exeloo - -# [@nanoforge-dev/sound@1.0.0](https://github.com/NanoForge-dev/Engine/tree/@nanoforge-dev/sound@1.0.0) - (2026-01-09) - -## Documentation - -- Update README files with new structure and detailed usage examples for all packages (#157) ([63fab73](https://github.com/NanoForge-dev/Engine/commit/63fab7326bd9c7e6b00f950694ab16c9d9190c53)) by @Exeloo -- Add funding (#147) ([7301fad](https://github.com/NanoForge-dev/Engine/commit/7301fad10f59b7e1f7fa788f8a2f6fc81d0db72e)) by @Exeloo -- Add a basic introduction readme ([b240964](https://github.com/NanoForge-dev/Engine/commit/b240964a265b31769a8c5422e23e20156ba56192)) by @MartinFillon -- Add building and dependency docs to every readme ([2d4785b](https://github.com/NanoForge-dev/Engine/commit/2d4785bdcb455e83337b37540f9ab6b3394c0850)) by @MartinFillon - -## Features - -- **core:** Enhance type safety and execution context handling ([d986030](https://github.com/NanoForge-dev/Engine/commit/d986030a333bc08d2e37291d1a023cf8d7a6e1d6)) by @Exeloo -- **app:** Add the ability to mute and unmute sounds ([947bdc0](https://github.com/NanoForge-dev/Engine/commit/947bdc00784a4c3313fe08feb4f91fc91b3ac7b7)) by @MartinFillon -- **sound:** Add basic sound playing to example ([7335814](https://github.com/NanoForge-dev/Engine/commit/7335814fc532ee92a5f9d776f409c5faa4d56423)) by @MartinFillon -- **sound:** Add sound playing ([e264dbc](https://github.com/NanoForge-dev/Engine/commit/e264dbcf87a52403e3a29b8c58cccbacae460ecf)) by @MartinFillon -- **sound:** Init basic sound library ([9cfc3d9](https://github.com/NanoForge-dev/Engine/commit/9cfc3d9dd9fe74b44f0f45705a4316c0699bbd79)) by @MartinFillon - -## Refactor - -- Change test engine (#126) ([ce2c71f](https://github.com/NanoForge-dev/Engine/commit/ce2c71fc1d1b5e3fb3ff4e86fd30aa77c969fbe0)) by @Exeloo -- Migrate namespaces to `@nanoforge-dev` and update related imports ([c84c927](https://github.com/NanoForge-dev/Engine/commit/c84c927ead941d914e5a9fd752fd3a5ac969f981)) by @Exeloo -- **libraries:** Implement initialization validation and standardize nullable fields ([8b04575](https://github.com/NanoForge-dev/Engine/commit/8b04575cf7f649a440b8f40ad6114414406b0c1a)) by @Exeloo -- **libs:** Remove `ECSContext` type in favor of `Context` ([b4ea6f1](https://github.com/NanoForge-dev/Engine/commit/b4ea6f1622b4a29cf57b9bfa1b715f56d248806e)) by @Exeloo - diff --git a/packages/sound/LICENSE b/packages/sound/LICENSE deleted file mode 100644 index 62c6400b..00000000 --- a/packages/sound/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright © 2025 NanoForge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/sound/cliff.toml b/packages/sound/cliff.toml deleted file mode 100644 index 5163767e..00000000 --- a/packages/sound/cliff.toml +++ /dev/null @@ -1,79 +0,0 @@ -[changelog] -header = """ -# Changelog - -All notable changes to this project will be documented in this file.\n -""" -body = """ -{%- macro remote_url() -%} - https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} -{%- endmacro -%} -{% if version %}\ - # [{{ version | trim_start_matches(pat="v") }}]\ - {% if previous %}\ - {% if previous.version %}\ - ({{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }})\ - {% else %}\ - ({{ self::remote_url() }}/tree/{{ version }})\ - {% endif %}\ - {% endif %} \ - - ({{ timestamp | date(format="%Y-%m-%d") }}) -{% else %}\ - # [unreleased] -{% endif %}\ -{% for group, commits in commits | group_by(attribute="group") %} - ## {{ group | upper_first }} - {% for commit in commits %} - - {% if commit.scope %}\ - **{{commit.scope}}:** \ - {% endif %}\ - {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ - {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ - {% if commit.breaking %}\ - {% for footer in commit.footers %}\ - {% if footer.breaking %}\ - \n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\ - {% endif %}\ - {% endfor %}\ - {% endif %}\ - {% endfor %} -{% endfor %}\ -{% if github.contributors | filter(attribute="is_first_time", value=true) | length %}\ - \n### New Contributors\n - {% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}\ - - @{{ contributor.username }} made their first contribution in #{{ contributor.pr_number }} - {% endfor %}\ -{% endif %}\n -""" -trim = true -footer = "" - -[git] -conventional_commits = true -filter_unconventional = true -commit_parsers = [ - { message = "^feat", group = "Features"}, - { message = "^fix", group = "Bug Fixes"}, - { message = "^docs", group = "Documentation"}, - { message = "^perf", group = "Performance"}, - { message = "^refactor", group = "Refactor"}, - { message = "^types", group = "Typings"}, - { message = ".*deprecated", body = ".*deprecated", group = "Deprecation"}, - { message = "^revert", skip = true}, - { message = "^style", group = "Styling"}, - { message = "^test", group = "Testing"}, - { message = "^chore", skip = true}, - { message = "^ci", skip = true}, - { message = "^build", skip = true}, - { body = ".*security", group = "Security"}, -] -filter_commits = true -protect_breaking_commits = true -tag_pattern = "^[0-9]+" -ignore_tags = "" -topo_order = false -sort_commits = "newest" - -[remote.github] -owner = "NanoForge-dev" -repo = "Engine" diff --git a/packages/sound/eslint.config.js b/packages/sound/eslint.config.js deleted file mode 100644 index 62ec06dc..00000000 --- a/packages/sound/eslint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-eslint-config"; - -export default config; diff --git a/packages/sound/prettier.config.js b/packages/sound/prettier.config.js deleted file mode 100644 index 27d0e269..00000000 --- a/packages/sound/prettier.config.js +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@nanoforge-dev/utils-prettier-config"; - -export default config; diff --git a/packages/sound/src/index.ts b/packages/sound/src/index.ts deleted file mode 100644 index ebf9eece..00000000 --- a/packages/sound/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { SoundLibrary } from "./sound.library"; diff --git a/packages/sound/src/sound.library.ts b/packages/sound/src/sound.library.ts deleted file mode 100644 index 1fd753d9..00000000 --- a/packages/sound/src/sound.library.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { BaseSoundLibrary, NfNotFound } from "@nanoforge-dev/common"; - -/** - * Built-in sound-effect library. - * - * @remarks - * Manages a collection of named `HTMLAudioElement` instances. Load sounds - * with `load` and trigger playback with `play`. Register with - * the application: - * - * ```ts - * client.useSound(new SoundLibrary()); - * ``` - * - * Access in game code: - * ```ts - * const sound = ctx.libraries.getSound().library; - * sound.load("explosion", "/sounds/explosion.mp3"); - * sound.play("explosion"); - * ``` - */ -export class SoundLibrary extends BaseSoundLibrary { - private muted: boolean = true; - private sounds?: Map; - - /** @internal */ - get __name(): string { - return "NfSound"; - } - - /** @internal */ - public async __init(): Promise { - this.sounds = new Map(); - this.muted = true; - } - - /** - * Toggle the muted state of all loaded sound effects. - * - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public mute(): void { - if (!this.sounds) this.throwNotInitializedError(); - this.muted = !this.muted; - for (const [, element] of this.sounds) { - if (element) { - element.muted = this.muted; - } - } - } - - /** - * Play a previously loaded sound effect. - * - * @param sound - Key that identifies the sound (as passed to load). - * @throws `NfNotFound` When no sound is registered under the given key. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public play(sound: string): void { - if (!this.sounds) this.throwNotInitializedError(); - const soundElement = this.sounds.get(sound); - - if (soundElement) { - soundElement - .play() - .then(() => {}) - .catch((e) => { - console.error(`Got error: ${e}`); - }); - } else { - throw new NfNotFound(sound); - } - } - - /** - * Register a sound effect under a unique key. - * - * @remarks - * Creates an `HTMLAudioElement` from the provided URL. The sound respects - * the current muted state at load time. - * - * @param sound - Unique key used to reference this sound (e.g. "explosion"). - * @param file - URL or path to the audio file. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public load(sound: string, file: string) { - if (!this.sounds) this.throwNotInitializedError(); - const element = new Audio(file); - if (element) { - element.muted = this.muted; - } - this.sounds.set(sound, element); - } -} diff --git a/packages/sound/tsconfig.json b/packages/sound/tsconfig.json deleted file mode 100644 index 1ada333c..00000000 --- a/packages/sound/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig.json", - "extends": "../../tsconfig.json", - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist"], - "compilerOptions": { - "declaration": true, - "paths": { - "/snippets/*": ["./docs/snippets/*"] - } - }, - "mdx": { - "checkMdx": true - } -} diff --git a/packages/sound/tsdoc.json b/packages/sound/tsdoc.json deleted file mode 100644 index ae9ae564..00000000 --- a/packages/sound/tsdoc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"], - "tagDefinitions": [ - { - "tagName": "@default", - "syntaxKind": "block", - "allowMultiple": false - } - ], - "supportForTags": { - "@default": true - } -} diff --git a/packages/sound/tsdown.config.ts b/packages/sound/tsdown.config.ts deleted file mode 100644 index 12f5dea6..00000000 --- a/packages/sound/tsdown.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createTsdownConfig } from "../../tsdown.config"; - -export default [createTsdownConfig()]; From 6b43460e715b3f82bb2668f27b7f69b7311d2fd3 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 11:50:29 +0200 Subject: [PATCH 05/12] feat: add new asset (#425) --- .../.cliff-jumperrc.json | 4 +- packages/{asset-manager => asset}/.gitignore | 0 .../{network-client => asset}/.prettierignore | 0 .../{asset-manager => asset}/CHANGELOG.md | 0 .../{graphics-2d-editor => asset}/LICENSE | 2 +- packages/{asset-manager => asset}/README.md | 2 +- packages/{graphics-2d => asset}/cliff.toml | 0 packages/{music => asset}/eslint.config.js | 0 .../mint-tsdocs.config.json | 0 .../{asset-manager => asset}/package.json | 13 ++-- packages/{input => asset}/prettier.config.js | 0 packages/asset/src/asset-library.ts | 65 ++++++++++++++++ packages/asset/src/index.ts | 1 + packages/asset/test/asset-library.spec.ts | 76 +++++++++++++++++++ packages/{input => asset}/tsconfig.json | 0 .../tsconfig.spec.json | 0 packages/{graphics-2d => asset}/tsdoc.json | 0 .../{ecs-server => asset}/tsdown.config.ts | 0 18 files changed, 153 insertions(+), 10 deletions(-) rename packages/{ecs-client => asset}/.cliff-jumperrc.json (75%) rename packages/{asset-manager => asset}/.gitignore (100%) rename packages/{network-client => asset}/.prettierignore (100%) rename packages/{asset-manager => asset}/CHANGELOG.md (100%) rename packages/{graphics-2d-editor => asset}/LICENSE (97%) rename packages/{asset-manager => asset}/README.md (98%) rename packages/{graphics-2d => asset}/cliff.toml (100%) rename packages/{music => asset}/eslint.config.js (100%) rename packages/{asset-manager => asset}/mint-tsdocs.config.json (100%) rename packages/{asset-manager => asset}/package.json (88%) rename packages/{input => asset}/prettier.config.js (100%) create mode 100644 packages/asset/src/asset-library.ts create mode 100644 packages/asset/src/index.ts create mode 100644 packages/asset/test/asset-library.spec.ts rename packages/{input => asset}/tsconfig.json (100%) rename packages/{network-server => asset}/tsconfig.spec.json (100%) rename packages/{graphics-2d => asset}/tsdoc.json (100%) rename packages/{ecs-server => asset}/tsdown.config.ts (100%) diff --git a/packages/ecs-client/.cliff-jumperrc.json b/packages/asset/.cliff-jumperrc.json similarity index 75% rename from packages/ecs-client/.cliff-jumperrc.json rename to packages/asset/.cliff-jumperrc.json index 6906e1ee..8dd6513f 100644 --- a/packages/ecs-client/.cliff-jumperrc.json +++ b/packages/asset/.cliff-jumperrc.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "ecs-client", + "name": "asset", "org": "nanoforge-dev", - "packagePath": "packages/ecs-client", + "packagePath": "packages/asset", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/asset-manager/.gitignore b/packages/asset/.gitignore similarity index 100% rename from packages/asset-manager/.gitignore rename to packages/asset/.gitignore diff --git a/packages/network-client/.prettierignore b/packages/asset/.prettierignore similarity index 100% rename from packages/network-client/.prettierignore rename to packages/asset/.prettierignore diff --git a/packages/asset-manager/CHANGELOG.md b/packages/asset/CHANGELOG.md similarity index 100% rename from packages/asset-manager/CHANGELOG.md rename to packages/asset/CHANGELOG.md diff --git a/packages/graphics-2d-editor/LICENSE b/packages/asset/LICENSE similarity index 97% rename from packages/graphics-2d-editor/LICENSE rename to packages/asset/LICENSE index 62c6400b..46724861 100644 --- a/packages/graphics-2d-editor/LICENSE +++ b/packages/asset/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/asset-manager/README.md b/packages/asset/README.md similarity index 98% rename from packages/asset-manager/README.md rename to packages/asset/README.md index ec968ef6..a0eaefeb 100644 --- a/packages/asset-manager/README.md +++ b/packages/asset/README.md @@ -19,7 +19,7 @@ ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/asset-manager diff --git a/packages/graphics-2d/cliff.toml b/packages/asset/cliff.toml similarity index 100% rename from packages/graphics-2d/cliff.toml rename to packages/asset/cliff.toml diff --git a/packages/music/eslint.config.js b/packages/asset/eslint.config.js similarity index 100% rename from packages/music/eslint.config.js rename to packages/asset/eslint.config.js diff --git a/packages/asset-manager/mint-tsdocs.config.json b/packages/asset/mint-tsdocs.config.json similarity index 100% rename from packages/asset-manager/mint-tsdocs.config.json rename to packages/asset/mint-tsdocs.config.json diff --git a/packages/asset-manager/package.json b/packages/asset/package.json similarity index 88% rename from packages/asset-manager/package.json rename to packages/asset/package.json index c3b9e33f..cb390655 100644 --- a/packages/asset-manager/package.json +++ b/packages/asset/package.json @@ -1,8 +1,8 @@ { "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/asset-manager", + "name": "@nanoforge-dev/asset", "version": "1.4.2", - "description": "NanoForge Engine - Asset Manager", + "description": "NanoForge Engine - Asset", "keywords": [ "nanoforge", "game", @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -43,7 +44,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/asset-manager" + "directory": "packages/asset" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -52,7 +53,7 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/asset-manager/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/asset/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, @@ -71,7 +72,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/input/prettier.config.js b/packages/asset/prettier.config.js similarity index 100% rename from packages/input/prettier.config.js rename to packages/asset/prettier.config.js diff --git a/packages/asset/src/asset-library.ts b/packages/asset/src/asset-library.ts new file mode 100644 index 00000000..c0a68310 --- /dev/null +++ b/packages/asset/src/asset-library.ts @@ -0,0 +1,65 @@ +import { + type AssetContext, + type InitContext, + Library, + NfFile, + NfNotFound, + defineLibraryKey, +} from "@nanoforge-dev/common"; + +export const ASSET_LIBRARY_KEY = "assets" as const; + +/** + * Built-in asset library. + * + * @remarks + * Auto-registered by `@nanoforge-dev/core` — app code never calls + * `app.use(new AssetLibrary())` directly. Stores the virtual file map + * injected by the NanoForge loader and exposes it via `getAsset`, always + * available on `Context.assets`. + * + * File paths are normalised on lookup: leading/duplicate slashes collapse + * to a single `/`, and a trailing slash is stripped. + */ +export class AssetLibrary extends Library { + readonly key = defineLibraryKey(ASSET_LIBRARY_KEY); + + private _assets?: Map; + + public override async __init(ctx: InitContext): Promise { + this._assets = ctx.files; + } + + /** + * Retrieve a registered file asset by its virtual path. + * + * @param path - Virtual path of the asset (e.g. "/textures/hero.png"). + * @returns An `NfFile` handle, or `undefined` if no path is given. + * @throws `NfNotFound` When no asset is registered at the given path. + * @throws `NfNotInitializedException` When called before `__init` resolves. + */ + public getAsset(path: string): NfFile; + public getAsset(path: "" | undefined): undefined; + public getAsset(path: string | undefined): NfFile | undefined { + if (!this._assets) this.throwNotInitializedError(); + if (!path) return undefined; + + const url = this._assets.get(this._normalize(path)); + if (!url) throw new NfNotFound(path, "Asset"); + return new NfFile(url); + } + + public override expose(): AssetContext { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + getAsset: (path: any): any => library.getAsset(path), + }; + } + + private _normalize(path: string): string { + const collapsed = path.replace(/\/{2,}/g, "/"); + const withLeadingSlash = collapsed.startsWith("/") ? collapsed : `/${collapsed}`; + return withLeadingSlash.length > 1 ? withLeadingSlash.replace(/\/+$/, "") : withLeadingSlash; + } +} diff --git a/packages/asset/src/index.ts b/packages/asset/src/index.ts new file mode 100644 index 00000000..b4dbb41a --- /dev/null +++ b/packages/asset/src/index.ts @@ -0,0 +1 @@ +export { ASSET_LIBRARY_KEY, AssetLibrary } from "./asset-library"; diff --git a/packages/asset/test/asset-library.spec.ts b/packages/asset/test/asset-library.spec.ts new file mode 100644 index 00000000..25869576 --- /dev/null +++ b/packages/asset/test/asset-library.spec.ts @@ -0,0 +1,76 @@ +import { type InitContext, NfNotFound, NfNotInitializedException } from "@nanoforge-dev/common"; +import { beforeEach, describe, expect, it } from "vitest"; + +import { AssetLibrary } from "../src"; + +const TEST_FILES = new Map([ + ["/test.png", "blob:http://localhost:3000/test.png"], + ["/test.wasm", "blob:http://localhost:3000/test.wasm"], + ["/test.wgsl", "blob:http://localhost:3000/test.wgsl"], +]); + +const makeInitContext = (files: Map): InitContext => ({ + vars: { get: () => undefined, set: () => {} }, + env: {}, + files, +}); + +describe("AssetLibrary", () => { + describe("metadata", () => { + it("should expose the reserved 'assets' key", () => { + expect(new AssetLibrary().key).toBe("assets"); + }); + }); + + describe("before initialization", () => { + it("should throw NfNotInitializedException when getAsset is called before __init", () => { + const library = new AssetLibrary(); + expect(() => library.getAsset("test.png")).toThrow(NfNotInitializedException); + }); + }); + + describe("getAsset", () => { + let library: AssetLibrary; + + beforeEach(async () => { + library = new AssetLibrary(); + await library.__init(makeInitContext(TEST_FILES)); + }); + + it("should return the correct path for a registered asset", () => { + expect(library.getAsset("test.png").path).toBe("blob:http://localhost:3000/test.png"); + }); + + it("should normalize a path with a leading slash", () => { + expect(library.getAsset("/test.png").path).toBe("blob:http://localhost:3000/test.png"); + }); + + it("should normalize a path with multiple leading slashes", () => { + expect(library.getAsset("//test.png").path).toBe("blob:http://localhost:3000/test.png"); + }); + + it("should normalize a path with a trailing slash", () => { + expect(library.getAsset("test.wasm/").path).toBe("blob:http://localhost:3000/test.wasm"); + }); + + it("should throw NfNotFound for an unknown asset", () => { + expect(() => library.getAsset("unknown.png")).toThrow(NfNotFound); + }); + + it("should return undefined for an empty or undefined path", () => { + expect(library.getAsset(undefined)).toBeUndefined(); + expect(library.getAsset("")).toBeUndefined(); + }); + }); + + describe("expose", () => { + it("should return a narrow object whose getAsset matches the instance method", async () => { + const library = new AssetLibrary(); + await library.__init(makeInitContext(TEST_FILES)); + + const exposed = library.expose(); + expect(exposed.getAsset("test.png").path).toBe("blob:http://localhost:3000/test.png"); + expect(Object.keys(exposed)).toEqual(["getAsset"]); + }); + }); +}); diff --git a/packages/input/tsconfig.json b/packages/asset/tsconfig.json similarity index 100% rename from packages/input/tsconfig.json rename to packages/asset/tsconfig.json diff --git a/packages/network-server/tsconfig.spec.json b/packages/asset/tsconfig.spec.json similarity index 100% rename from packages/network-server/tsconfig.spec.json rename to packages/asset/tsconfig.spec.json diff --git a/packages/graphics-2d/tsdoc.json b/packages/asset/tsdoc.json similarity index 100% rename from packages/graphics-2d/tsdoc.json rename to packages/asset/tsdoc.json diff --git a/packages/ecs-server/tsdown.config.ts b/packages/asset/tsdown.config.ts similarity index 100% rename from packages/ecs-server/tsdown.config.ts rename to packages/asset/tsdown.config.ts From 4eb632ce6a10edc673d8a3e909adcf53c55c8ebd Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 11:50:57 +0200 Subject: [PATCH 06/12] feat: add new common (#423) --- packages/common/.nvmrc | 1 - packages/common/LICENSE | 2 +- packages/common/README.md | 2 +- packages/common/package.json | 5 +- packages/common/src/common/file.ts | 6 +- packages/common/src/context/context.type.ts | 71 ++++++++ .../context/contexts/application.context.ts | 35 ---- .../src/context/contexts/client.context.ts | 20 --- .../contexts/executions/base.context.ts | 39 ----- .../contexts/executions/clear.context.ts | 10 -- .../contexts/executions/execution.context.ts | 10 -- .../src/context/contexts/executions/index.ts | 3 - .../contexts/executions/init.context.ts | 83 --------- packages/common/src/context/contexts/index.ts | 4 - .../src/context/contexts/library.context.ts | 26 --- packages/common/src/context/index.ts | 3 +- .../common/src/context/init-context.type.ts | 49 ++++++ .../common/src/editor/event-emitter.type.ts | 23 +++ packages/common/src/editor/index.ts | 1 + .../exception/abstracts/exception.abstract.ts | 18 +- .../exception/exceptions/config.exception.ts | 24 --- .../exceptions/duplicate-library.exception.ts | 19 ++ .../exception/exceptions/fetch.exception.ts | 7 +- .../exceptions/not-found.exception.ts | 19 +- .../exceptions/not-initialized.exception.ts | 12 +- packages/common/src/exception/index.ts | 3 +- .../exception/interfaces/exception.type.ts | 3 - packages/common/src/index.ts | 4 +- packages/common/src/library/config/index.ts | 1 - .../config/interfaces/config-registry.type.ts | 36 ---- .../common/src/library/define-library-key.ts | 28 +++ packages/common/src/library/index.ts | 6 +- .../asset-manager.library.abstract.ts | 28 --- .../component-system.library.abstract.ts | 20 --- .../abstracts/graphics.library.abstract.ts | 16 -- .../src/library/libraries/abstracts/index.ts | 7 - .../abstracts/input.library.abstract.ts | 16 -- .../abstracts/music.library.abstract.ts | 32 ---- .../abstracts/network.library.abstract.ts | 12 -- .../abstracts/sound.library.abstract.ts | 32 ---- .../src/library/libraries/consts/index.ts | 1 - .../libraries/consts/library-label.const.ts | 64 ------- .../consts/library-options-default.const.ts | 7 - .../common/src/library/libraries/index.ts | 6 - .../interfaces/bases/exposed.library.type.ts | 11 -- .../interfaces/bases/mutable.library.type.ts | 14 -- .../interfaces/bases/runner.library.type.ts | 15 -- .../finals/asset-manager.library.type.ts | 22 --- .../finals/component-system.library.type.ts | 13 -- .../finals/graphics.library.type.ts | 12 -- .../interfaces/finals/input.library.type.ts | 12 -- .../interfaces/finals/music.library.type.ts | 12 -- .../interfaces/finals/network.library.type.ts | 11 -- .../interfaces/finals/sound.library.type.ts | 12 -- .../src/library/libraries/interfaces/index.ts | 10 -- .../common/src/library/libraries/library.ts | 75 -------- .../src/library/libraries/library.type.ts | 51 ------ packages/common/src/library/library.ts | 92 ++++++++++ .../library/manager/handle/library.handle.ts | 51 ------ packages/common/src/library/manager/index.ts | 3 - .../manager/managers/base-library.manager.ts | 38 ---- .../managers/client-library.manager.ts | 105 ----------- .../manager/managers/library.manager.ts | 146 ---------------- .../common/src/library/relationship.type.ts | 18 ++ .../relationship/relationship-handler.ts | 30 ---- packages/common/src/options/index.ts | 1 - .../common/src/options/types/options.type.ts | 63 ------- .../common/test/define-library-key.spec-d.ts | 16 ++ .../common/test/define-library-key.spec.ts | 9 + packages/common/test/exceptions.spec.ts | 29 ++-- packages/common/test/library.spec.ts | 164 +++--------------- packages/common/tsconfig.spec.json | 2 +- .../{core-editor => env}/.cliff-jumperrc.json | 4 +- packages/{music => env}/.gitignore | 41 ----- .../{network-server => env}/.prettierignore | 0 packages/env/CHANGELOG.md | 3 + packages/{graphics-2d => env}/LICENSE | 2 +- packages/env/README.md | 123 +++++++++++++ packages/{input => env}/cliff.toml | 0 .../{network-client => env}/eslint.config.js | 0 .../{ecs-lib => env}/mint-tsdocs.config.json | 2 +- packages/{network-client => env}/package.json | 16 +- packages/{music => env}/prettier.config.js | 0 .../env/src/decorators/default.decorator.ts | 16 ++ .../src/decorators/is-ip-or-url.decorator.ts} | 27 +-- .../transform-to-boolean.decorator.ts} | 17 +- .../src/exports/class-transformer.ts | 0 .../src/exports/class-validator.ts | 0 packages/env/src/index.ts | 7 + .../src/registry/env-validation.exception.ts | 16 ++ packages/env/src/registry/register-env.ts | 27 +++ packages/env/test/default.spec.ts | 40 +++++ packages/env/test/is-ip-or-url.spec.ts | 28 +++ packages/env/test/register-env.spec.ts | 33 ++++ .../env/test/transform-to-boolean.spec.ts | 25 +++ packages/{music => env}/tsconfig.json | 0 packages/env/tsconfig.spec.json | 10 ++ packages/{input => env}/tsdoc.json | 0 .../tsdown.config.ts | 0 99 files changed, 741 insertions(+), 1547 deletions(-) delete mode 100644 packages/common/.nvmrc create mode 100644 packages/common/src/context/context.type.ts delete mode 100644 packages/common/src/context/contexts/application.context.ts delete mode 100644 packages/common/src/context/contexts/client.context.ts delete mode 100644 packages/common/src/context/contexts/executions/base.context.ts delete mode 100644 packages/common/src/context/contexts/executions/clear.context.ts delete mode 100644 packages/common/src/context/contexts/executions/execution.context.ts delete mode 100644 packages/common/src/context/contexts/executions/index.ts delete mode 100644 packages/common/src/context/contexts/executions/init.context.ts delete mode 100644 packages/common/src/context/contexts/index.ts delete mode 100644 packages/common/src/context/contexts/library.context.ts create mode 100644 packages/common/src/context/init-context.type.ts create mode 100644 packages/common/src/editor/event-emitter.type.ts create mode 100644 packages/common/src/editor/index.ts delete mode 100644 packages/common/src/exception/exceptions/config.exception.ts create mode 100644 packages/common/src/exception/exceptions/duplicate-library.exception.ts delete mode 100644 packages/common/src/exception/interfaces/exception.type.ts delete mode 100644 packages/common/src/library/config/index.ts delete mode 100644 packages/common/src/library/config/interfaces/config-registry.type.ts create mode 100644 packages/common/src/library/define-library-key.ts delete mode 100644 packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/abstracts/index.ts delete mode 100644 packages/common/src/library/libraries/abstracts/input.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/abstracts/music.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/abstracts/network.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/abstracts/sound.library.abstract.ts delete mode 100644 packages/common/src/library/libraries/consts/index.ts delete mode 100644 packages/common/src/library/libraries/consts/library-label.const.ts delete mode 100644 packages/common/src/library/libraries/consts/library-options-default.const.ts delete mode 100644 packages/common/src/library/libraries/index.ts delete mode 100644 packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/input.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/music.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/network.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts delete mode 100644 packages/common/src/library/libraries/interfaces/index.ts delete mode 100644 packages/common/src/library/libraries/library.ts delete mode 100644 packages/common/src/library/libraries/library.type.ts create mode 100644 packages/common/src/library/library.ts delete mode 100644 packages/common/src/library/manager/handle/library.handle.ts delete mode 100644 packages/common/src/library/manager/index.ts delete mode 100644 packages/common/src/library/manager/managers/base-library.manager.ts delete mode 100644 packages/common/src/library/manager/managers/client-library.manager.ts delete mode 100644 packages/common/src/library/manager/managers/library.manager.ts create mode 100644 packages/common/src/library/relationship.type.ts delete mode 100644 packages/common/src/library/relationship/relationship-handler.ts delete mode 100644 packages/common/src/options/index.ts delete mode 100644 packages/common/src/options/types/options.type.ts create mode 100644 packages/common/test/define-library-key.spec-d.ts create mode 100644 packages/common/test/define-library-key.spec.ts rename packages/{core-editor => env}/.cliff-jumperrc.json (75%) rename packages/{music => env}/.gitignore (91%) rename packages/{network-server => env}/.prettierignore (100%) create mode 100644 packages/env/CHANGELOG.md rename packages/{graphics-2d => env}/LICENSE (97%) create mode 100644 packages/env/README.md rename packages/{input => env}/cliff.toml (100%) rename packages/{network-client => env}/eslint.config.js (100%) rename packages/{ecs-lib => env}/mint-tsdocs.config.json (82%) rename packages/{network-client => env}/package.json (86%) rename packages/{music => env}/prettier.config.js (100%) create mode 100644 packages/env/src/decorators/default.decorator.ts rename packages/{config/src/validators/is-ip-or-url.validator.ts => env/src/decorators/is-ip-or-url.decorator.ts} (57%) rename packages/{config/src/transformers/boolean.transformer.ts => env/src/decorators/transform-to-boolean.decorator.ts} (55%) rename packages/{config => env}/src/exports/class-transformer.ts (100%) rename packages/{config => env}/src/exports/class-validator.ts (100%) create mode 100644 packages/env/src/index.ts create mode 100644 packages/env/src/registry/env-validation.exception.ts create mode 100644 packages/env/src/registry/register-env.ts create mode 100644 packages/env/test/default.spec.ts create mode 100644 packages/env/test/is-ip-or-url.spec.ts create mode 100644 packages/env/test/register-env.spec.ts create mode 100644 packages/env/test/transform-to-boolean.spec.ts rename packages/{music => env}/tsconfig.json (100%) create mode 100644 packages/env/tsconfig.spec.json rename packages/{input => env}/tsdoc.json (100%) rename packages/{graphics-2d-editor => env}/tsdown.config.ts (100%) diff --git a/packages/common/.nvmrc b/packages/common/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/common/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/common/LICENSE b/packages/common/LICENSE index 62c6400b..46724861 100644 --- a/packages/common/LICENSE +++ b/packages/common/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/common/README.md b/packages/common/README.md index a874391b..00b64f28 100644 --- a/packages/common/README.md +++ b/packages/common/README.md @@ -19,7 +19,7 @@ ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/common diff --git a/packages/common/package.json b/packages/common/package.json index daf766aa..9341306b 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -68,7 +69,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/common/src/common/file.ts b/packages/common/src/common/file.ts index 376ac68d..d545570b 100644 --- a/packages/common/src/common/file.ts +++ b/packages/common/src/common/file.ts @@ -4,8 +4,8 @@ import { NfFetchException } from "../exception"; * Represents a file asset that has been registered with the engine. * * @remarks - * Instances are returned by `AssetManagerLibrary.getAsset`. Each method - * lazily fetches the file from the engine's virtual file system and returns the + * Instances are returned by `AssetContext.getAsset`. Each method lazily + * fetches the file from the engine's virtual file system and returns the * content in the requested format. * * All read methods throw `NfFetchException` when the underlying `fetch` @@ -13,7 +13,7 @@ import { NfFetchException } from "../exception"; * * @example * ```ts - * const file = assetManager.getAsset("/textures/hero.png"); + * const file = asset.getAsset("/textures/hero.png"); * const buffer = await file.arrayBuffer(); * ``` */ diff --git a/packages/common/src/context/context.type.ts b/packages/common/src/context/context.type.ts new file mode 100644 index 00000000..b4bd95cc --- /dev/null +++ b/packages/common/src/context/context.type.ts @@ -0,0 +1,71 @@ +import type { NfFile } from "../common/file"; + +/** + * Read-only application state plus the actions available to affect it. + * + * @remarks + * `AppContext` deliberately exposes no setters — mutation only happens + * internally, inside `@nanoforge-dev/core`. Game code and libraries can read + * state and call actions, but can never reach into and directly overwrite + * engine-owned state. + */ +export interface AppContext { + /** Whether the engine's tick loop is currently running. */ + readonly isRunning: boolean; + /** Whether the tick loop is currently paused (no library's `__run` is called while paused). */ + readonly isPaused: boolean; + /** Elapsed time in milliseconds since the last tick. Does not advance while paused. */ + readonly delta: number; + /** Configured ticks-per-second for the run loop. */ + readonly tickRate: number; + /** Requests that the tick loop stop after the current tick. */ + requestStop(): void; + /** Pauses the tick loop: every library's `__run` is skipped until resumed. */ + requestPause(): void; + /** Resumes a paused tick loop. */ + requestResume(): void; +} + +/** + * A typed, dev-editable key/value bag shared across all libraries and game + * code for the lifetime of a run. + * + * @typeParam TVars - Shape of the variables bag. Defaults to an untyped + * `Record` when no shape is declared. + */ +export interface VarsContext = Record> { + get(key: K): TVars[K]; + set(key: K, value: TVars[K]): void; +} + +/** + * Public surface of the engine's built-in asset library, always present on + * `Context.assets` regardless of which libraries an app registers. + */ +export interface AssetContext { + getAsset(path: string): NfFile; + getAsset(path: "" | undefined): undefined; +} + +/** + * The context object handed to every library's `__run`/`__clear` hooks and + * to game code. + * + * @remarks + * `app`, `vars` and `assets` are always present (core-provided). Every other + * key is contributed by a registered `Library` via its `expose()` method. + * Library packages add their own key by augmenting this interface: + * + * ```ts + * declare module "@nanoforge-dev/common" { + * interface Context { + * ecs: EcsContextApi; + * } + * } + * ``` + */ +export interface Context { + readonly app: AppContext; + readonly vars: VarsContext; + readonly assets: AssetContext; +} diff --git a/packages/common/src/context/contexts/application.context.ts b/packages/common/src/context/contexts/application.context.ts deleted file mode 100644 index 96a7f12f..00000000 --- a/packages/common/src/context/contexts/application.context.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Holds runtime state that is shared across all libraries during the game loop. - * - * @remarks - * An instance of this class is available to every library via - * `BaseContext.application`. Libraries may read `isRunning` and `delta` - * to make frame-rate-independent decisions. - */ -export abstract class ApplicationContext { - private _isRunning: boolean = false; - /** @internal */ - protected _delta!: number; - - /** - * Whether the engine game loop is currently executing. - */ - get isRunning(): boolean { - return this._isRunning; - } - - /** - * Elapsed time in milliseconds since the last frame. - */ - get delta(): number { - return this._delta; - } - - /** @internal */ - setIsRunning(value: boolean): void { - this._isRunning = value; - } - - /** @internal */ - abstract muteSoundLibraries(): void; -} diff --git a/packages/common/src/context/contexts/client.context.ts b/packages/common/src/context/contexts/client.context.ts deleted file mode 100644 index a491a93b..00000000 --- a/packages/common/src/context/contexts/client.context.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { type ClientLibraryManager } from "../../library"; -import type { ApplicationContext } from "./application.context"; - -export class Context { - private readonly _applicationContext: ApplicationContext; - private readonly _libraryManager: ClientLibraryManager; - - constructor(applicationContext: ApplicationContext, libraryManager: ClientLibraryManager) { - this._applicationContext = applicationContext; - this._libraryManager = libraryManager; - } - - get app(): ApplicationContext { - return this._applicationContext; - } - - get libs(): ClientLibraryManager { - return this._libraryManager; - } -} diff --git a/packages/common/src/context/contexts/executions/base.context.ts b/packages/common/src/context/contexts/executions/base.context.ts deleted file mode 100644 index d5ab9e24..00000000 --- a/packages/common/src/context/contexts/executions/base.context.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { type LibraryManager } from "../../../library/manager/managers/library.manager"; -import { type ApplicationContext } from "../application.context"; - -/** - * Base context passed to library lifecycle hooks. - * - * @remarks - * All execution context types (`InitContext`, `ClearContext`, - * `ExecutionContext`) extend this class and expose `application` and - * `libraries`. - */ -export class BaseContext { - private readonly _applicationContext: ApplicationContext; - private readonly _libraryManager: LibraryManager; - - /** - * @param applicationContext - Shared application-level runtime state. - * @param libraryManager - Manager giving access to all registered libraries. - */ - constructor(applicationContext: ApplicationContext, libraryManager: LibraryManager) { - this._applicationContext = applicationContext; - this._libraryManager = libraryManager; - } - - /** - * Shared application-level runtime state (running flag, delta time, …). - */ - get application(): ApplicationContext { - return this._applicationContext; - } - - /** - * Manager that provides typed access to every library registered with the - * current application. - */ - 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 deleted file mode 100644 index ba8889a4..00000000 --- a/packages/common/src/context/contexts/executions/clear.context.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BaseContext } from "./base.context"; - -/** - * Context passed to a library's `__clear` lifecycle hook during application shutdown. - * - * @remarks - * Use the inherited `application` and `libraries` accessors to access shared - * state and other libraries while tearing down resources. - */ -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 deleted file mode 100644 index eae4a5cd..00000000 --- a/packages/common/src/context/contexts/executions/execution.context.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BaseContext } from "./base.context"; - -/** - * Context passed to a library's `__run` hook on every game-loop tick. - * - * @remarks - * Use the inherited `application` and `libraries` accessors to read the current - * delta time and interact with other libraries during the frame update. - */ -export class ExecutionContext extends BaseContext {} diff --git a/packages/common/src/context/contexts/executions/index.ts b/packages/common/src/context/contexts/executions/index.ts deleted file mode 100644 index 25d298ba..00000000 --- a/packages/common/src/context/contexts/executions/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 328771c8..00000000 --- a/packages/common/src/context/contexts/executions/init.context.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { type IConfigRegistry, type LibraryManager } from "../../../library"; -import { type IRunClientOptions, type IRunOptions } from "../../../options"; -import { type ApplicationContext } from "../application.context"; -import { BaseContext } from "./base.context"; - -/** - * Context object passed to every library's `__init` lifecycle hook. - * - * @remarks - * Provides libraries with all the information they need during start-up: - * the canvas container, pre-loaded asset files, environment variables, and a - * config registry for loading structured configuration classes. - * - * Access it in a library's `__init` override: - * ```ts - * override async __init(ctx: InitContext) { - * const config = await ctx.config.registerConfig(MyConfig); - * const file = ctx.libraries.getAssetManager().library.getAsset("/data.json"); - * } - * ``` - */ -export class InitContext extends BaseContext { - private readonly _container: IRunClientOptions["container"] | undefined; - private readonly _files: IRunOptions["files"]; - private readonly _env: Record; - private readonly _config: IConfigRegistry; - - /** - * @param context - Shared application-level runtime state. - * @param libraryManager - Manager giving access to other registered libraries. - * @param configRegistry - Registry used to resolve typed configuration objects. - * @param options - Run options forwarded from NanoforgeApplication.init. - */ - constructor( - context: ApplicationContext, - libraryManager: LibraryManager, - configRegistry: IConfigRegistry, - options: IRunOptions, - ) { - super(context, libraryManager); - - this._container = (options as IRunClientOptions)["container"]; - this._files = options.files; - this._env = options.env; - this._config = configRegistry; - } - - /** - * The `HTMLDivElement` that should host the game canvas. - * - * @remarks - * Only available in client contexts; `undefined` on the server. - */ - get container(): IRunClientOptions["container"] | undefined { - return this._container; - } - - /** - * Map of virtual file paths to their URL strings, pre-loaded by the engine bundler. - */ - get files(): IRunOptions["files"] { - return this._files; - } - - /** - * Key/value map of environment variables made available at runtime. - */ - get env(): Record { - return this._env; - } - - /** - * Registry that resolves class-validator/class-transformer decorated - * configuration classes from the runtime environment. - * - * @remarks - * Call `ctx.config.registerConfig(MyConfigClass)` to get a validated and - * transformed instance populated from `ctx.env`. - */ - get config(): IConfigRegistry { - return this._config; - } -} diff --git a/packages/common/src/context/contexts/index.ts b/packages/common/src/context/contexts/index.ts deleted file mode 100644 index 19e85e08..00000000 --- a/packages/common/src/context/contexts/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./executions"; -export { ApplicationContext } from "./application.context"; -export { Context } from "./client.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 deleted file mode 100644 index 1b58eb06..00000000 --- a/packages/common/src/context/contexts/library.context.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Lifecycle states a library can be in. - */ -export enum LibraryStatusEnum { - /** The library has not been initialised yet. */ - UNLOADED = "UNLOADED", - /** The library has been successfully initialised and is ready to use. */ - LOADED = "LOADED", - /** The library has been cleared and its resources released. */ - CLEAR = "CLEAR", -} - -/** - * Tracks the current lifecycle state of a single library registration. - */ -export class LibraryContext { - /** @internal */ - protected _status: LibraryStatusEnum = LibraryStatusEnum.UNLOADED; - - /** - * Current lifecycle state of the associated library. - */ - get status() { - return this._status; - } -} diff --git a/packages/common/src/context/index.ts b/packages/common/src/context/index.ts index 315ff978..c28b0258 100644 --- a/packages/common/src/context/index.ts +++ b/packages/common/src/context/index.ts @@ -1 +1,2 @@ -export * from "./contexts"; +export type { AppContext, AssetContext, Context, VarsContext } from "./context.type"; +export type { ClientRunOptions, InitContext, RunOptions } from "./init-context.type"; diff --git a/packages/common/src/context/init-context.type.ts b/packages/common/src/context/init-context.type.ts new file mode 100644 index 00000000..796a4038 --- /dev/null +++ b/packages/common/src/context/init-context.type.ts @@ -0,0 +1,49 @@ +import { type EventEmitter } from "../editor"; +import type { VarsContext } from "./context.type"; + +/** + * Options every NanoForge application is started with. + */ +export interface RunOptions { + /** Virtual file system, injected by the NanoForge loader. */ + files: Map; + /** Raw, unvalidated environment variables. */ + env: Record; + + /** + * Raw editor bridge, supplied by whoever starts the app under an editor + * host. `EditorLibrary` transforms this pair into the single + * `Context.editor` facade every library sees. + */ + editor?: { + /** Engine → editor channel. */ + toEditor: EventEmitter; + /** Editor → engine channel. */ + fromEditor: EventEmitter; + }; +} + +/** + * Options a client application is started with. + */ +export interface ClientRunOptions extends RunOptions { + /** DOM element the client should render into. */ + container: HTMLDivElement; +} + +/** + * Narrow context available to a library's `__init` hook. + * + * @remarks + * `app` and `assets` are intentionally absent here: `app` doesn't exist yet + * (the tick loop hasn't started), and `assets` isn't populated until every + * library has finished initializing. Libraries that need raw files during + * `__init` (e.g. the built-in asset library) read `files` directly. + */ +export interface InitContext { + vars: VarsContext; + env: Record; + files: Map; + container?: HTMLDivElement; + editor?: RunOptions["editor"]; +} diff --git a/packages/common/src/editor/event-emitter.type.ts b/packages/common/src/editor/event-emitter.type.ts new file mode 100644 index 00000000..e9d4502f --- /dev/null +++ b/packages/common/src/editor/event-emitter.type.ts @@ -0,0 +1,23 @@ +/** + * A generic, queued event emitter. + * + * @remarks + * "Queued" means `emit` doesn't invoke listeners synchronously — it enqueues + * the event, and `runEvents()` drains the queue, invoking listeners once per + * call. This lets an event arriving mid-tick (e.g. from a WebSocket handler) + * be applied at a controlled point instead of interrupting whatever else is + * running. + * + * @typeParam Events - Union of event name literals. + * @typeParam EventsMap - Maps each event name to its listener argument tuple. + */ +export interface EventEmitter< + Events extends string = string, + EventsMap extends Record = Record, +> { + on(event: K, listener: (...args: EventsMap[K]) => void): void; + off(event: K, listener: (...args: EventsMap[K]) => void): void; + emit(event: K, ...args: EventsMap[K]): void; + /** Drains the queue, synchronously invoking listeners for each queued event. */ + runEvents(): void; +} diff --git a/packages/common/src/editor/index.ts b/packages/common/src/editor/index.ts new file mode 100644 index 00000000..49d31358 --- /dev/null +++ b/packages/common/src/editor/index.ts @@ -0,0 +1 @@ +export type { EventEmitter } from "./event-emitter.type"; diff --git a/packages/common/src/exception/abstracts/exception.abstract.ts b/packages/common/src/exception/abstracts/exception.abstract.ts index 2e6e4985..63053fa9 100644 --- a/packages/common/src/exception/abstracts/exception.abstract.ts +++ b/packages/common/src/exception/abstracts/exception.abstract.ts @@ -1,32 +1,16 @@ -import type { INfException } from "../interfaces/exception.type"; - /** * Base class for all NanoForge engine exceptions. * * @remarks * All errors thrown by the engine extend this class so that game code can * differentiate engine errors from unrelated runtime errors. - * - * @example - * ```ts - * try { - * assetManager.getAsset("/missing.png"); - * } catch (err) { - * if (err instanceof NfException) { - * console.error(err.code, err.message); - * } - * } - * ``` */ -export abstract class NfException extends Error implements INfException { +export abstract class NfException extends Error { /** * HTTP-style numeric code identifying the error category. */ abstract get code(): number; - /** - * @param message - Optional human-readable description of the error. - */ protected constructor(message?: string) { super( message ? `[NANOFORGE] ${message}` : "[NANOFORGE] An error occurred (Unknown exception).", diff --git a/packages/common/src/exception/exceptions/config.exception.ts b/packages/common/src/exception/exceptions/config.exception.ts deleted file mode 100644 index 3f4f4b9e..00000000 --- a/packages/common/src/exception/exceptions/config.exception.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { NfException } from "../abstracts/exception.abstract"; - -/** - * Thrown when a library configuration is invalid or incomplete. - * - * @remarks - * Typically raised during `__init` when required environment variables are - * missing or fail validation. For example, `NetworkClientLibrary` throws this - * when neither `SERVER_TCP_PORT` nor `SERVER_UDP_PORT` is provided. - */ -export class NfConfigException extends NfException { - /** Always `400`. */ - get code(): number { - return 400; - } - - /** - * @param message - Description of the configuration error. - * @param library - Optional library name that detected the error. - */ - constructor(message: string, library?: string) { - super(`Config Exception ${library ? `(${library}) ` : ""}- ${message}`); - } -} diff --git a/packages/common/src/exception/exceptions/duplicate-library.exception.ts b/packages/common/src/exception/exceptions/duplicate-library.exception.ts new file mode 100644 index 00000000..cbe25ef4 --- /dev/null +++ b/packages/common/src/exception/exceptions/duplicate-library.exception.ts @@ -0,0 +1,19 @@ +import { NfException } from "../abstracts/exception.abstract"; + +/** + * Thrown when two libraries are registered under the same context key, or + * when a library tries to register under a reserved key (`"app"`, `"vars"`, + * `"assets"`). + */ +export class NfDuplicateLibraryException extends NfException { + get code(): number { + return 409; + } + + /** + * @param key - The context key that was already taken or is reserved. + */ + constructor(key: string) { + super(`Library key "${key}" is already registered or reserved.`); + } +} diff --git a/packages/common/src/exception/exceptions/fetch.exception.ts b/packages/common/src/exception/exceptions/fetch.exception.ts index 35409e6e..3aa3f608 100644 --- a/packages/common/src/exception/exceptions/fetch.exception.ts +++ b/packages/common/src/exception/exceptions/fetch.exception.ts @@ -4,15 +4,12 @@ import { NfException } from "../abstracts/exception.abstract"; * Thrown when an HTTP fetch performed internally by the engine fails. * * @remarks - * Raised by `NfFile` methods (e.g. `arrayBuffer`, `text`) when the - * underlying `fetch` call returns a non-OK HTTP response. + * Raised by `NfFile` methods when the underlying `fetch` call returns a + * non-OK HTTP response. */ export class NfFetchException extends NfException { private readonly _code: number; - /** - * The HTTP status code returned by the failed request (e.g. `404`, `500`). - */ get code(): number { return this._code; } diff --git a/packages/common/src/exception/exceptions/not-found.exception.ts b/packages/common/src/exception/exceptions/not-found.exception.ts index 57f313e8..a467fa2a 100644 --- a/packages/common/src/exception/exceptions/not-found.exception.ts +++ b/packages/common/src/exception/exceptions/not-found.exception.ts @@ -1,30 +1,17 @@ import { NfException } from "../abstracts/exception.abstract"; /** - * Thrown when a requested resource (asset, sound, music track, etc.) cannot - * be found in the engine's registry. - * - * @example - * ```ts - * // Thrown automatically by AssetManagerLibrary.getAsset, SoundLibrary.play, etc. - * try { - * const file = assetManager.getAsset("/textures/hero.png"); - * } catch (err) { - * if (err instanceof NfNotFound) { - * console.error("Missing resource:", err.message); - * } - * } - * ``` + * Thrown when a requested resource (asset, library-contributed context key, + * etc.) cannot be found. */ export class NfNotFound extends NfException { - /** Always `404`. */ get code(): number { return 404; } /** * @param item - Name or path of the missing resource. - * @param type - Optional category label (e.g. "Asset", "Sound"). + * @param type - Optional category label (e.g. "Asset"). */ constructor(item: string, type?: string) { super(`${type ? `${type} - ` : ""}${item} not found.`); diff --git a/packages/common/src/exception/exceptions/not-initialized.exception.ts b/packages/common/src/exception/exceptions/not-initialized.exception.ts index 61deec33..b5cf5404 100644 --- a/packages/common/src/exception/exceptions/not-initialized.exception.ts +++ b/packages/common/src/exception/exceptions/not-initialized.exception.ts @@ -1,23 +1,19 @@ import { NfException } from "../abstracts/exception.abstract"; /** - * Thrown when a method is called on a library or engine component before it - * has been initialised via `__init`. + * Thrown when a library is used before its `__init` lifecycle hook has + * resolved. * * @remarks - * This exception is raised automatically by the helper method - * `Library.throwNotInitializedError()`. Ensure that - * `NanoforgeApplication.init` has resolved before interacting with any - * library. + * Raised automatically by `Library.throwNotInitializedError()`. */ export class NfNotInitializedException extends NfException { - /** Always `404`. */ get code(): number { return 404; } /** - * @param item - Name of the uninitialised component (e.g. the library's __name). + * @param item - Key of the uninitialised library. * @param type - Optional category label (e.g. "Library"). */ constructor(item: string, type?: string) { diff --git a/packages/common/src/exception/index.ts b/packages/common/src/exception/index.ts index ae691faa..5864df39 100644 --- a/packages/common/src/exception/index.ts +++ b/packages/common/src/exception/index.ts @@ -1,4 +1,5 @@ -export { NfConfigException } from "./exceptions/config.exception"; +export { NfException } from "./abstracts/exception.abstract"; +export { NfDuplicateLibraryException } from "./exceptions/duplicate-library.exception"; export { NfFetchException } from "./exceptions/fetch.exception"; export { NfNotFound } from "./exceptions/not-found.exception"; export { NfNotInitializedException } from "./exceptions/not-initialized.exception"; diff --git a/packages/common/src/exception/interfaces/exception.type.ts b/packages/common/src/exception/interfaces/exception.type.ts deleted file mode 100644 index 33ea46db..00000000 --- a/packages/common/src/exception/interfaces/exception.type.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface INfException extends Error { - get code(): number; -} diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 5adc5c5b..426c83ba 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,5 +1,5 @@ export * from "./common"; export * from "./context"; -export * from "./library"; -export * from "./options"; +export * from "./editor"; export * from "./exception"; +export * from "./library"; diff --git a/packages/common/src/library/config/index.ts b/packages/common/src/library/config/index.ts deleted file mode 100644 index b838944c..00000000 --- a/packages/common/src/library/config/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./interfaces/config-registry.type"; diff --git a/packages/common/src/library/config/interfaces/config-registry.type.ts b/packages/common/src/library/config/interfaces/config-registry.type.ts deleted file mode 100644 index bbd4e24e..00000000 --- a/packages/common/src/library/config/interfaces/config-registry.type.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Resolves and validates typed configuration objects from the runtime - * environment. - * - * @remarks - * An instance is available in `InitContext.config`. Configuration - * classes must be decorated with `class-transformer` (`@Expose`, `@Default`) - * and `class-validator` (`@IsPort`, `@IsIpOrURL`, etc.) decorators from - * `@nanoforge-dev/config`. - * - * @example - * ```ts - * import `Expose, IsPort ` from "@nanoforge-dev/config"; - * - * class MyConfig { - * \@Expose() \@IsPort() - * PORT!: string; - * } - * - * // Inside __init: - * const cfg = await ctx.config.registerConfig(MyConfig); - * console.log(cfg.PORT); - * ``` - */ -export interface IConfigRegistry { - /** - * Instantiate, populate from the runtime environment, transform, and - * validate a configuration class. - * - * @typeParam T - Configuration class type. - * @param config - Constructor of the configuration class. - * @returns A validated, populated instance of the configuration class. - * @throws `NfConfigException` When validation fails. - */ - registerConfig(config: new () => T): Promise; -} diff --git a/packages/common/src/library/define-library-key.ts b/packages/common/src/library/define-library-key.ts new file mode 100644 index 00000000..72b29bfc --- /dev/null +++ b/packages/common/src/library/define-library-key.ts @@ -0,0 +1,28 @@ +import type { Context } from "../context"; + +/** + * Declares a library's context key, tying its runtime key to the type-level + * `Context` augmentation so the two can't silently desync. + * + * @remarks + * Only accepts a key that is already a member of `Context` at the call + * site — which means the library's own `declare module "@nanoforge-dev/common" + * { interface Context { ... } }` augmentation must be part of the same + * compilation unit. As a side effect, two libraries whose augmentations + * declare the same key with incompatible shapes will fail to compile + * together, catching accidental key collisions at build time. + * + * @example + * ```ts + * class MyLibrary extends Library { + * readonly key = defineLibraryKey("my"); + * } + * + * declare module "@nanoforge-dev/common" { + * interface Context { + * my: MyContextApi; + * } + * } + * ``` + */ +export const defineLibraryKey = (key: K): K => key; diff --git a/packages/common/src/library/index.ts b/packages/common/src/library/index.ts index 089b3727..5278df51 100644 --- a/packages/common/src/library/index.ts +++ b/packages/common/src/library/index.ts @@ -1,3 +1,3 @@ -export * from "./config"; -export * from "./libraries"; -export * from "./manager"; +export { defineLibraryKey } from "./define-library-key"; +export { Library } from "./library"; +export { DEFAULT_LIBRARY_RELATIONSHIPS, type LibraryRelationships } from "./relationship.type"; 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 deleted file mode 100644 index 23973afb..00000000 --- a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { type NfFile } from "../../../common"; -import { type InitContext } from "../../../context"; -import { type IAssetManagerLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for asset-manager libraries. - * - * @remarks - * Extend this class to implement a custom asset-manager and register it with - * `NanoforgeApplication.useAssetManager`. The built-in implementation - * is `AssetManagerLibrary`. - */ -export abstract class BaseAssetManagerLibrary extends Library implements IAssetManagerLibrary { - /** @internal */ - public abstract override __init(context: InitContext): Promise; - - /** - * Retrieve a file asset by its virtual path. - * - * @param path - Virtual path as registered in the engine's file map (e.g. "/textures/hero.png"). - * @returns An `NfFile` handle that lazily fetches the asset content. - * @throws `NfNotFound` When no asset is registered at the given path. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public abstract getAsset(path: string): NfFile; - public abstract getAsset(path: "" | undefined): undefined; -} 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 deleted file mode 100644 index a00f9015..00000000 --- a/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { type Context } from "../../../context"; -import { type IComponentSystemLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for component-system (ECS) libraries. - * - * @remarks - * Extend this class (or the higher-level `AbstractECSLibrary`) to - * implement a custom ECS back-end and register it with - * `NanoforgeApplication.useComponentSystem`. The built-in - * implementations are `ECSClientLibrary` and `ECSServerLibrary`. - */ -export abstract class BaseComponentSystemLibrary - extends Library - implements IComponentSystemLibrary -{ - /** @internal */ - abstract __run(context: Context): 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 deleted file mode 100644 index ed1baa9b..00000000 --- a/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { type Context } from "../../../context"; -import { type IGraphicsLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for graphics libraries. - * - * @remarks - * Extend this class to implement a custom rendering backend and register it - * with `NanoforgeClient.useGraphics`. The built-in implementation is - * `Graphics2DLibrary`. - */ -export abstract class BaseGraphicsLibrary extends Library implements IGraphicsLibrary { - /** @internal */ - abstract __run(context: Context): Promise; -} diff --git a/packages/common/src/library/libraries/abstracts/index.ts b/packages/common/src/library/libraries/abstracts/index.ts deleted file mode 100644 index b31b3db0..00000000 --- a/packages/common/src/library/libraries/abstracts/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -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 { BaseSoundLibrary } from "./sound.library.abstract"; -export { BaseNetworkLibrary } from "./network.library.abstract"; -export { BaseMusicLibrary } from "./music.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 deleted file mode 100644 index 69256a41..00000000 --- a/packages/common/src/library/libraries/abstracts/input.library.abstract.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { type Context } from "../../../context"; -import { type IInputLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for input libraries. - * - * @remarks - * Extend this class to implement a custom input back-end and register it with - * `NanoforgeClient.useInput`. The built-in implementation is - * `InputLibrary`. - */ -export abstract class BaseInputLibrary extends Library implements IInputLibrary { - /** @internal */ - public abstract __run(_context: Context): Promise; -} diff --git a/packages/common/src/library/libraries/abstracts/music.library.abstract.ts b/packages/common/src/library/libraries/abstracts/music.library.abstract.ts deleted file mode 100644 index 71614876..00000000 --- a/packages/common/src/library/libraries/abstracts/music.library.abstract.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { type InitContext } from "../../../context"; -import { type IMusicLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for music libraries. - * - * @remarks - * Extend this class to implement a custom music library and register it with - * `NanoforgeApplication.use` using the `MUSIC_LIBRARY` symbol. - * The built-in implementation is `MusicLibrary`. - */ -export abstract class BaseMusicLibrary extends Library implements IMusicLibrary { - /** @internal */ - public abstract override __init(context: InitContext): Promise; - - /** - * Stop the currently playing track (if any) and start playing the requested one. - * - * @param sound - Key that identifies the music track (as passed to load). - * @throws `NfNotFound` When no track is registered under the given key. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public abstract play(sound: string): void; - - /** - * Toggle the muted state of all loaded music tracks. - * - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public abstract mute(): void; -} diff --git a/packages/common/src/library/libraries/abstracts/network.library.abstract.ts b/packages/common/src/library/libraries/abstracts/network.library.abstract.ts deleted file mode 100644 index 1e793150..00000000 --- a/packages/common/src/library/libraries/abstracts/network.library.abstract.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type INetworkLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for network libraries. - * - * @remarks - * Extend this class to implement a custom network library and register it with - * `NanoforgeApplication.useNetwork`. The built-in implementations are - * `NetworkClientLibrary` and `NetworkServerLibrary`. - */ -export abstract class BaseNetworkLibrary extends Library implements INetworkLibrary {} diff --git a/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts b/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts deleted file mode 100644 index 7e4ea5cb..00000000 --- a/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { type InitContext } from "../../../context"; -import { type ISoundLibrary } from "../interfaces"; -import { Library } from "../library"; - -/** - * Abstract base class for sound libraries. - * - * @remarks - * Extend this class to implement a custom sound library and register it with - * `NanoforgeClient.useSound`. The built-in implementation is - * `SoundLibrary`. - */ -export abstract class BaseSoundLibrary extends Library implements ISoundLibrary { - /** @internal */ - public abstract override __init(context: InitContext): Promise; - - /** - * Play a previously loaded sound effect. - * - * @param sound - Key that identifies the sound (as passed to load). - * @throws `NfNotFound` When no sound is registered under the given key. - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public abstract play(sound: string): void; - - /** - * Toggle the muted state of all loaded sound effects. - * - * @throws `NfNotInitializedException` When called before `__init` has resolved. - */ - public abstract mute(): void; -} diff --git a/packages/common/src/library/libraries/consts/index.ts b/packages/common/src/library/libraries/consts/index.ts deleted file mode 100644 index e8609d9a..00000000 --- a/packages/common/src/library/libraries/consts/index.ts +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index d99b0150..00000000 --- a/packages/common/src/library/libraries/consts/library-label.const.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Registration symbol for the component-system (ECS) library slot. - * - * @remarks - * Pass this symbol to `NanoforgeApplication.use` when registering a - * custom component-system library, or use the shorthand - * `NanoforgeApplication.useComponentSystem`. - */ -export const COMPONENT_SYSTEM_LIBRARY = Symbol("COMPONENT_SYSTEM_LIBRARY"); - -/** - * Registration symbol for the graphics library slot. - * - * @remarks - * Pass this symbol to `NanoforgeClient.useGraphics` or use it as a - * dependency symbol in a custom library's `ILibraryOptions.dependencies`. - */ -export const GRAPHICS_LIBRARY = Symbol("GRAPHICS_LIBRARY"); - -/** - * Registration symbol for the network library slot. - * - * @remarks - * Pass this symbol to `NanoforgeApplication.useNetwork` or use it as a - * dependency symbol in a custom library's `ILibraryOptions.dependencies`. - */ -export const NETWORK_LIBRARY = Symbol("NETWORK_LIBRARY"); - -/** - * Registration symbol for the sound library slot. - * - * @remarks - * Pass this symbol to `NanoforgeClient.useSound` or use it as a - * dependency symbol in a custom library's `ILibraryOptions.dependencies`. - */ -export const SOUND_LIBRARY = Symbol("SOUND_LIBRARY"); - -/** - * Registration symbol for the music library slot. - * - * @remarks - * Pass this symbol to `NanoforgeApplication.use` with a custom music - * library or use it as a dependency symbol in - * `ILibraryOptions.dependencies`. - */ -export const MUSIC_LIBRARY = Symbol("MUSIC_LIBRARY"); - -/** - * Registration symbol for the asset-manager library slot. - * - * @remarks - * Pass this symbol to `NanoforgeApplication.useAssetManager` or use it - * as a dependency in a custom library's `ILibraryOptions.dependencies`. - */ -export const ASSET_MANAGER_LIBRARY = Symbol("ASSET_MANAGER_LIBRARY"); - -/** - * Registration symbol for the input library slot. - * - * @remarks - * Pass this symbol to `NanoforgeClient.useInput` or use it as a - * dependency symbol in a custom library's `ILibraryOptions.dependencies`. - */ -export const INPUT_LIBRARY = Symbol("INPUT_LIBRARY"); diff --git a/packages/common/src/library/libraries/consts/library-options-default.const.ts b/packages/common/src/library/libraries/consts/library-options-default.const.ts deleted file mode 100644 index 01698c15..00000000 --- a/packages/common/src/library/libraries/consts/library-options-default.const.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { type ILibraryOptions } from "../library.type"; - -export const DEFAULT_LIBRARY_OPTIONS: ILibraryOptions = { - dependencies: [], - runBefore: [], - runAfter: [], -}; diff --git a/packages/common/src/library/libraries/index.ts b/packages/common/src/library/libraries/index.ts deleted file mode 100644 index 8ce9096f..00000000 --- a/packages/common/src/library/libraries/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type { ILibrary } from "./library.type"; -export { Library } from "./library"; - -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 deleted file mode 100644 index fb2d18b6..00000000 --- a/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type ILibrary } from "../../library.type"; - -/** - * Marker interface for libraries that are directly accessible to game code via - * the `ClientLibraryManager`. - * - * @remarks - * All built-in typed library interfaces (e.g. `IAssetManagerLibrary`, - * `ISoundLibrary`) extend this interface. - */ -export interface IExposedLibrary extends ILibrary {} diff --git a/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts b/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts deleted file mode 100644 index aa5aee08..00000000 --- a/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { type ILibrary } from "../../library.type"; - -/** - * Interface for libraries that support muting/unmuting audio playback. - * - * @remarks - * Implemented by `ISoundLibrary` and `IMusicLibrary`. - */ -export interface IMutableLibrary extends ILibrary { - /** - * Toggle the muted state. Mutes when currently unmuted, and vice versa. - */ - mute(): void; -} 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 deleted file mode 100644 index ac6df49e..00000000 --- a/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type Context } from "../../../../context"; -import { type ILibrary } from "../../library.type"; - -/** - * Interface for libraries that participate in the per-frame game loop. - * - * @remarks - * The engine calls `__run` on every tick for all registered runner libraries - * in the order determined by their `ILibraryOptions.runBefore` / - * `ILibraryOptions.runAfter` relationships. - */ -export interface IRunnerLibrary extends ILibrary { - /** @internal */ - __run(context: Context): 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 deleted file mode 100644 index 216708bb..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { type NfFile } from "../../../../common"; -import { type IExposedLibrary } from "../bases/exposed.library.type"; - -/** - * Interface for asset-manager libraries. - * - * @remarks - * Implemented by `BaseAssetManagerLibrary` and its concrete subclass - * `AssetManagerLibrary`. Access an instance via - * `ctx.libraries.getAssetManager().library`. - */ -export interface IAssetManagerLibrary extends IExposedLibrary { - /** - * Retrieve a registered file asset by its virtual path. - * - * @param path - Virtual path of the asset (e.g. "/textures/hero.png"). - * @returns An `NfFile` handle for the requested asset, or `undefined` if no asset path is provided. - * @throws `NfNotFound` When no asset is registered at the given path. - */ - getAsset(path: string): NfFile; - getAsset(path: "" | undefined): undefined; -} 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 deleted file mode 100644 index 8208b886..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { type IExposedLibrary } from "../bases/exposed.library.type"; -import { type IRunnerLibrary } from "../bases/runner.library.type"; - -/** - * Interface for component-system (ECS) libraries. - * - * @remarks - * Implemented by `BaseComponentSystemLibrary` and the higher-level - * `AbstractECSLibrary`, with concrete subclasses - * `ECSClientLibrary` and `ECSServerLibrary`. Access an instance - * via `ctx.libraries.getComponentSystem().library`. - */ -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 deleted file mode 100644 index 9509a9dd..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type IExposedLibrary } from "../bases/exposed.library.type"; -import { type IRunnerLibrary } from "../bases/runner.library.type"; - -/** - * Interface for graphics libraries. - * - * @remarks - * Implemented by `BaseGraphicsLibrary` and its concrete subclass - * `Graphics2DLibrary`. Access an instance via - * `ctx.libraries.getGraphics().library`. - */ -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 deleted file mode 100644 index 9dc79452..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type IExposedLibrary } from "../bases/exposed.library.type"; -import { type IRunnerLibrary } from "../bases/runner.library.type"; - -/** - * Interface for input libraries. - * - * @remarks - * Implemented by `BaseInputLibrary` and its concrete subclass - * `InputLibrary`. Access an instance via - * `ctx.libraries.getInput().library`. - */ -export interface IInputLibrary extends IExposedLibrary, IRunnerLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts deleted file mode 100644 index 653e918d..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type IExposedLibrary } from "../bases/exposed.library.type"; -import { type IMutableLibrary } from "../bases/mutable.library.type"; - -/** - * Interface for music libraries. - * - * @remarks - * Implemented by `BaseMusicLibrary` and its concrete subclass - * `MusicLibrary`. Access an instance via - * `ctx.libraries.getMusic().library`. - */ -export interface IMusicLibrary extends IExposedLibrary, IMutableLibrary {} 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 deleted file mode 100644 index 80d0bca5..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type IExposedLibrary } from "../bases/exposed.library.type"; - -/** - * Interface for network libraries. - * - * @remarks - * Implemented by `BaseNetworkLibrary` and its concrete subclasses - * `NetworkClientLibrary` and `NetworkServerLibrary`. Access an - * instance via `ctx.libraries.getNetwork().library`. - */ -export interface INetworkLibrary extends IExposedLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts deleted file mode 100644 index 8ce0fb79..00000000 --- a/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type IExposedLibrary } from "../bases/exposed.library.type"; -import { type IMutableLibrary } from "../bases/mutable.library.type"; - -/** - * Interface for sound-effect libraries. - * - * @remarks - * Implemented by `BaseSoundLibrary` and its concrete subclass - * `SoundLibrary`. Access an instance via - * `ctx.libraries.getSound().library`. - */ -export interface ISoundLibrary extends IExposedLibrary, IMutableLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/index.ts b/packages/common/src/library/libraries/interfaces/index.ts deleted file mode 100644 index 226fe953..00000000 --- a/packages/common/src/library/libraries/interfaces/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type { IExposedLibrary } from "./bases/exposed.library.type"; -export type { IRunnerLibrary } from "./bases/runner.library.type"; -export type { IAssetManagerLibrary } from "./finals/asset-manager.library.type"; -export type { IComponentSystemLibrary } from "./finals/component-system.library.type"; -export type { IGraphicsLibrary } from "./finals/graphics.library.type"; -export type { IInputLibrary } from "./finals/input.library.type"; -export type { ISoundLibrary } from "./finals/sound.library.type"; -export type { INetworkLibrary } from "./finals/network.library.type"; -export type { IMusicLibrary } from "./finals/music.library.type"; -export type { IMutableLibrary } from "./bases/mutable.library.type"; diff --git a/packages/common/src/library/libraries/library.ts b/packages/common/src/library/libraries/library.ts deleted file mode 100644 index e7624558..00000000 --- a/packages/common/src/library/libraries/library.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { type ClearContext, type InitContext } from "../../context"; -import { NfNotInitializedException } from "../../exception"; -import { RelationshipHandler } from "../relationship/relationship-handler"; -import { DEFAULT_LIBRARY_OPTIONS } from "./consts/library-options-default.const"; -import { type ILibrary, type ILibraryOptions } from "./library.type"; - -/** - * Base class for all NanoForge libraries. - * - * @remarks - * Extend this class (or one of its typed subclasses such as - * `BaseAssetManagerLibrary`, `BaseSoundLibrary`, etc.) to create a - * custom library. At minimum you must implement the `ILibrary.__name` - * getter and register the library with the engine before calling - * `NanoforgeApplication.init`. - * - * @example - * ```ts - * import `Library, type InitContext ` from "@nanoforge-dev/common"; - * - * const MY_LIBRARY = Symbol("MY_LIBRARY"); - * - * class MyLibrary extends Library { - * get __name() `return "MyLibrary"; ` - * - * override async __init(ctx: InitContext) { - * // one-time setup here - * } - * } - * - * const client = NanoforgeFactory.createClient(); - * client.use(MY_LIBRARY, new MyLibrary()); - * await client.init(`container, files, env `); - * ``` - */ -export abstract class Library implements ILibrary { - protected _relationship: RelationshipHandler; - - /** - * @param rawOptions - Optional dependency and execution-order overrides. - */ - constructor(rawOptions?: Partial) { - const options = { - ...DEFAULT_LIBRARY_OPTIONS, - ...rawOptions, - }; - - this._relationship = new RelationshipHandler( - options.dependencies, - options.runBefore, - options.runAfter, - ); - } - - /** @internal */ - get __relationship(): RelationshipHandler { - return this._relationship; - } - - /** @internal */ - abstract get __name(): string; - - /** @internal */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - public async __init(_context: InitContext): Promise {} - - /** @internal */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - public async __clear(_context: ClearContext): Promise {} - - /** @internal */ - protected throwNotInitializedError(): never { - throw new NfNotInitializedException(this.__name, "Library"); - } -} diff --git a/packages/common/src/library/libraries/library.type.ts b/packages/common/src/library/libraries/library.type.ts deleted file mode 100644 index 35591bf2..00000000 --- a/packages/common/src/library/libraries/library.type.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { type ClearContext, type InitContext } from "../../context"; -import { type RelationshipHandler } from "../relationship/relationship-handler"; - -/** - * Core interface that every NanoForge library must satisfy. - * - * @remarks - * Implement this interface (or extend an abstract base such as `BaseAssetManagerLibrary`) - * to create a custom library and register it with the engine via - * `NanoforgeApplication.use`. - */ -export interface ILibrary { - /** @internal */ - get __name(): string; - - /** @internal */ - get __relationship(): RelationshipHandler; - - /** @internal */ - __init(context: InitContext): Promise; - - /** @internal */ - __clear(context: ClearContext): Promise; -} - -/** - * Options that control how a library participates in the engine's - * initialisation and execution ordering. - */ -export interface ILibraryOptions { - /** - * Symbols of libraries that must be fully initialised before this library - * can be used. - * - * @remarks - * The engine will reject configurations where a dependency is missing. - */ - dependencies: symbol[]; - - /** - * Symbols of libraries whose `__run` method should be called *after* this - * library's `__run`. - */ - runBefore: symbol[]; - - /** - * Symbols of libraries whose `__run` method must complete *before* this - * library's `__run` is invoked. - */ - runAfter: symbol[]; -} diff --git a/packages/common/src/library/library.ts b/packages/common/src/library/library.ts new file mode 100644 index 00000000..189857b0 --- /dev/null +++ b/packages/common/src/library/library.ts @@ -0,0 +1,92 @@ +import type { Context, InitContext } from "../context"; +import { NfNotInitializedException } from "../exception"; +import { DEFAULT_LIBRARY_RELATIONSHIPS, type LibraryRelationships } from "./relationship.type"; + +/** + * Base class for all NanoForge libraries. + * + * @remarks + * Extend this class to create a custom library, then register an instance + * with `app.use(new MyLibrary())`. A library owns its own context key (see + * `defineLibraryKey`), which is simultaneously its registry identity, its + * slot on `Context`, and the identifier used in `dependencies`/`runBefore`/ + * `runAfter`. + * + * @example + * ```ts + * import { Library, defineLibraryKey, type InitContext } from "@nanoforge-dev/common"; + * + * class MyLibrary extends Library { + * readonly key = defineLibraryKey("my"); + * + * override async __init(ctx: InitContext) { + * // one-time setup here + * } + * } + * + * app.use(new MyLibrary()); + * ``` + */ +export abstract class Library { + /** + * This library's identity: its slot on `Context`, its registry key, and + * the identifier used to reference it in ordering relationships. + */ + abstract readonly key: string; + + private readonly _relationships: LibraryRelationships; + + /** + * @param relationships - Optional ordering overrides, keyed by other + * libraries' `key`. + */ + constructor(relationships?: Partial) { + this._relationships = { + ...DEFAULT_LIBRARY_RELATIONSHIPS, + ...relationships, + }; + } + + /** @internal */ + get relationships(): LibraryRelationships { + return this._relationships; + } + + /** Called once, in dependency order, before the tick loop starts. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async __init(_ctx: InitContext): Promise {} + + /** + * Called every tick, in run order, whether or not the tick loop is + * paused — unlike `__run`. Use this for event/message draining that must + * not be affected by pause (e.g. an editor bridge listening for the + * "resume" command itself), not for gameplay simulation. + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async __events(_ctx: Context): Promise {} + + /** Called every tick, in run order, while the tick loop is active and not paused. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async __run(_ctx: Context): Promise {} + + /** Called once after the tick loop stops. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async __clear(_ctx: Context): Promise {} + + /** + * Returns this library's public contribution to `Context[this.key]`. + * + * @remarks + * Return a plain object exposing only what game code should be able to + * reach — never `this` — so internal state and lifecycle hooks never leak + * onto `Context`. Libraries with nothing to expose (headless libraries) + * can leave this unimplemented; they simply won't appear on `Context`. + */ + expose(): unknown { + return undefined; + } + + protected throwNotInitializedError(): never { + throw new NfNotInitializedException(this.key, "Library"); + } +} diff --git a/packages/common/src/library/manager/handle/library.handle.ts b/packages/common/src/library/manager/handle/library.handle.ts deleted file mode 100644 index 32bf268c..00000000 --- a/packages/common/src/library/manager/handle/library.handle.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { type LibraryContext } from "../../../context"; -import { type ILibrary } from "../../libraries"; - -/** - * An opaque handle returned by `LibraryManager` accessors. - * - * @remarks - * Bundles the library instance together with its registration symbol and - * lifecycle context. Prefer using the strongly-typed accessor methods on - * `LibraryManager` or `ClientLibraryManager` rather than - * constructing handles directly. - * - * @typeParam T - Concrete library type (defaults to `ILibrary`). - */ -export class LibraryHandle { - private readonly _symbol: symbol; - private readonly _library: T; - private readonly _context: LibraryContext; - - /** - * @param sym - Registration symbol for this library. - * @param library - The library instance. - * @param defaultContext - Initial lifecycle context. - */ - constructor(sym: symbol, library: T, defaultContext: LibraryContext) { - this._symbol = sym; - this._library = library; - this._context = defaultContext; - } - - /** - * The registration symbol used to look up this library. - */ - get symbol(): symbol { - return this._symbol; - } - - /** - * The underlying library instance. - */ - get library(): T { - return this._library; - } - - /** - * Current lifecycle context tracking the library's status. - */ - get context(): LibraryContext { - return this._context; - } -} diff --git a/packages/common/src/library/manager/index.ts b/packages/common/src/library/manager/index.ts deleted file mode 100644 index e44f1e38..00000000 --- a/packages/common/src/library/manager/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { LibraryHandle } from "./handle/library.handle"; -export { ClientLibraryManager } from "./managers/client-library.manager"; -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 deleted file mode 100644 index fe8be8cc..00000000 --- a/packages/common/src/library/manager/managers/base-library.manager.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { type LibraryContext } from "../../../context"; -import { type ILibrary } from "../../libraries"; -import { LibraryHandle } from "../handle/library.handle"; -import { DefaultLibrariesEnum } from "./library.manager"; - -export class BaseLibraryManager { - protected _libraries: LibraryHandle[] = []; - private _librariesIndex: Record = {}; - - /** - * @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 = Math.max(this._libraries.length, Object.keys(DefaultLibrariesEnum).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/client-library.manager.ts b/packages/common/src/library/manager/managers/client-library.manager.ts deleted file mode 100644 index 44127935..00000000 --- a/packages/common/src/library/manager/managers/client-library.manager.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { - type IAssetManagerLibrary, - type IComponentSystemLibrary, - type IGraphicsLibrary, - type IInputLibrary, - type ILibrary, - type IMusicLibrary, - type INetworkLibrary, - type ISoundLibrary, -} from "../../libraries"; -import { type LibraryManager } from "./library.manager"; - -/** - * Convenience wrapper around `LibraryManager` that unwraps - * `LibraryHandle` values and returns the library instance directly. - * - * @remarks - * Typically accessed inside a library's lifecycle hooks through the execution - * context's `libraries` property after being constructed with a concrete - * `LibraryManager`. - */ -export class ClientLibraryManager { - private readonly _libraryManager: LibraryManager; - - /** - * @param libraryManager - The underlying manager to delegate lookups to. - */ - constructor(libraryManager: LibraryManager) { - this._libraryManager = libraryManager; - } - - /** - * Retrieve a library registered under a custom symbol. - * - * @typeParam T - Expected library type. - * @param sym - The symbol the library was registered with. - * @returns The unwrapped library instance. - */ - public get(sym: symbol): T { - return this._libraryManager.get(sym).library; - } - - /** - * Retrieve the registered component-system (ECS) library instance. - * - * @typeParam T - Concrete component-system library type. - */ - public getComponentSystem(): T { - return this._libraryManager.getComponentSystem().library; - } - - /** - * Retrieve the registered graphics library instance. - * - * @typeParam T - Concrete graphics library type. - */ - public getGraphics(): T { - return this._libraryManager.getGraphics().library; - } - - /** - * Retrieve the registered network library instance. - * - * @typeParam T - Concrete network library type. - */ - public getNetwork(): T { - return this._libraryManager.getNetwork().library; - } - - /** - * Retrieve the registered input library instance. - * - * @typeParam T - Concrete input library type. - */ - public getInput(): T { - return this._libraryManager.getInput().library; - } - - /** - * Retrieve the registered asset-manager library instance. - * - * @typeParam T - Concrete asset-manager library type. - */ - public getAssetManager(): T { - return this._libraryManager.getAssetManager().library; - } - - /** - * Retrieve the registered sound library instance. - * - * @typeParam T - Concrete sound library type. - */ - public getSound(): T { - return this._libraryManager.getSound().library; - } - - /** - * Retrieve the registered music library instance. - * - * @typeParam T - Concrete music library type. - */ - public getMusic(): T { - return this._libraryManager.getMusic().library; - } -} diff --git a/packages/common/src/library/manager/managers/library.manager.ts b/packages/common/src/library/manager/managers/library.manager.ts deleted file mode 100644 index 22c7df83..00000000 --- a/packages/common/src/library/manager/managers/library.manager.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { - ASSET_MANAGER_LIBRARY, - COMPONENT_SYSTEM_LIBRARY, - GRAPHICS_LIBRARY, - type IAssetManagerLibrary, - type IComponentSystemLibrary, - type IGraphicsLibrary, - type IInputLibrary, - type IMusicLibrary, - type INetworkLibrary, - type ISoundLibrary, - MUSIC_LIBRARY, - NETWORK_LIBRARY, - SOUND_LIBRARY, -} from "../../libraries"; -import { type LibraryHandle } from "../handle/library.handle"; -import { BaseLibraryManager } from "./base-library.manager"; - -/** - * Numeric index keys for the built-in library slots. - * - * @remarks - * Used internally by `LibraryManager` to keep O(1) access to the well-known - * library positions. Game code should not reference these values directly — - * use the typed accessor methods on `LibraryManager` instead. - */ -export enum DefaultLibrariesEnum { - ASSET_MANAGER, - COMPONENT_SYSTEM, - GRAPHICS, - INPUT, - NETWORK, - SOUND, - MUSIC, -} - -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.GRAPHICS, sym: GRAPHICS_LIBRARY }, - { index: DefaultLibrariesEnum.NETWORK, sym: NETWORK_LIBRARY }, - { index: DefaultLibrariesEnum.SOUND, sym: SOUND_LIBRARY }, - { index: DefaultLibrariesEnum.MUSIC, sym: MUSIC_LIBRARY }, -]; - -/** - * Central registry for all libraries registered with a NanoForge application. - * - * @remarks - * An instance is available inside every lifecycle context via - * `BaseContext.libraries`. Use the typed accessor methods to retrieve - * any built-in library, or call `BaseLibraryManager.get` with a custom - * symbol for user-defined libraries. - * - * @example - * ```ts - * // Inside a library's __init hook: - * override async __init(ctx: InitContext) { - * const assetMgr = ctx.libraries.getAssetManager().library; - * const file = assetMgr.getAsset("/data.json"); - * } - * ``` - */ -export class LibraryManager extends BaseLibraryManager { - constructor() { - super(); - - for (const { index, sym } of DEFAULT_LIBRARIES) { - this._setIndex(sym, index); - } - } - - /** - * Retrieve the registered component-system (ECS) library. - * - * @typeParam T - Concrete component-system library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getComponentSystem< - T extends IComponentSystemLibrary = IComponentSystemLibrary, - >(): LibraryHandle { - return this._get(DefaultLibrariesEnum.COMPONENT_SYSTEM); - } - - /** - * Retrieve the registered graphics library. - * - * @typeParam T - Concrete graphics library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getGraphics(): LibraryHandle { - return this._get(DefaultLibrariesEnum.GRAPHICS); - } - - /** - * Retrieve the registered network library. - * - * @typeParam T - Concrete network library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getNetwork(): LibraryHandle { - return this._get(DefaultLibrariesEnum.NETWORK); - } - - /** - * Retrieve the registered input library. - * - * @typeParam T - Concrete input library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getInput(): LibraryHandle { - return this._get(DefaultLibrariesEnum.INPUT); - } - - /** - * Retrieve the registered asset-manager library. - * - * @typeParam T - Concrete asset-manager library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getAssetManager< - T extends IAssetManagerLibrary = IAssetManagerLibrary, - >(): LibraryHandle { - return this._get(DefaultLibrariesEnum.ASSET_MANAGER); - } - - /** - * Retrieve the registered sound library. - * - * @typeParam T - Concrete sound library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getSound(): LibraryHandle { - return this._get(DefaultLibrariesEnum.SOUND); - } - - /** - * Retrieve the registered music library. - * - * @typeParam T - Concrete music library type. - * @returns A `LibraryHandle` wrapping the library instance. - */ - public getMusic(): LibraryHandle { - return this._get(DefaultLibrariesEnum.MUSIC); - } -} diff --git a/packages/common/src/library/relationship.type.ts b/packages/common/src/library/relationship.type.ts new file mode 100644 index 00000000..2d68b80e --- /dev/null +++ b/packages/common/src/library/relationship.type.ts @@ -0,0 +1,18 @@ +/** + * Ordering relationships between a library and other libraries, referenced + * by their `key`. + */ +export interface LibraryRelationships { + /** Keys of libraries that must be initialized before this one. */ + dependencies: string[]; + /** Keys of libraries this one must run before, each tick. */ + runBefore: string[]; + /** Keys of libraries this one must run after, each tick. */ + runAfter: string[]; +} + +export const DEFAULT_LIBRARY_RELATIONSHIPS: LibraryRelationships = { + dependencies: [], + runBefore: [], + runAfter: [], +}; diff --git a/packages/common/src/library/relationship/relationship-handler.ts b/packages/common/src/library/relationship/relationship-handler.ts deleted file mode 100644 index 4c5ae313..00000000 --- a/packages/common/src/library/relationship/relationship-handler.ts +++ /dev/null @@ -1,30 +0,0 @@ -export class RelationshipHandler { - private readonly _dependencies: symbol[]; - private readonly _runBefore: symbol[]; - private readonly _runAfter: symbol[]; - - /** - * Constructor for RelationshipHandler - * - * @param dependencies - Dependencies of the library - * @param runBefore - Libraries needed to run before this one - * @param runAfter - Libraries needed to run after this one - */ - constructor(dependencies: symbol[], runBefore: symbol[], runAfter: symbol[]) { - this._dependencies = dependencies; - this._runBefore = runBefore; - this._runAfter = runAfter; - } - - get dependencies(): symbol[] { - return this._dependencies; - } - - get runBefore(): symbol[] { - return this._runBefore; - } - - get runAfter(): symbol[] { - return this._runAfter; - } -} diff --git a/packages/common/src/options/index.ts b/packages/common/src/options/index.ts deleted file mode 100644 index 32ab2502..00000000 --- a/packages/common/src/options/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { IRunClientOptions, IRunOptions, IRunServerOptions } from "./types/options.type"; diff --git a/packages/common/src/options/types/options.type.ts b/packages/common/src/options/types/options.type.ts deleted file mode 100644 index b24150ec..00000000 --- a/packages/common/src/options/types/options.type.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Union of client and server run options accepted by - * `NanoforgeApplication.init`. - */ -export type IRunOptions = IRunClientOptions | IRunServerOptions; - -/** - * Run options for a client-side NanoForge application. - * - * @remarks - * Pass an instance to `NanoforgeApplication.init` when running in the - * browser. The engine bundler (`nf build`) automatically generates and - * injects `files` and `env` at build time. - */ -export interface IRunClientOptions { - /** - * DOM element that will host the game canvas. - * - * @remarks - * The element's current `offsetWidth` and `offsetHeight` are used to set - * the initial canvas dimensions. - */ - container: HTMLDivElement; - - /** - * Map of virtual file paths to their resolved URL strings. - * - * @remarks - * Populated automatically by the NanoForge bundler. Keys are normalised - * paths such as `"/textures/hero.png"`. - */ - files: Map; - - /** - * Runtime environment variables available to all libraries via - * `InitContext.env`. - */ - env: Record; -} - -/** - * Run options for a server-side NanoForge application. - * - * @remarks - * Pass an instance to `NanoforgeApplication.init` when running in a - * Node.js server process. - */ -export interface IRunServerOptions { - /** - * Map of virtual file paths to their resolved URL strings. - * - * @remarks - * Populated automatically by the NanoForge bundler. Keys are normalised - * paths such as `"/data/config.json"`. - */ - files: Map; - - /** - * Runtime environment variables available to all libraries via - * `InitContext.env`. - */ - env: Record; -} diff --git a/packages/common/test/define-library-key.spec-d.ts b/packages/common/test/define-library-key.spec-d.ts new file mode 100644 index 00000000..71896803 --- /dev/null +++ b/packages/common/test/define-library-key.spec-d.ts @@ -0,0 +1,16 @@ +import { describe, it } from "vitest"; + +import { defineLibraryKey } from "../src"; + +describe("defineLibraryKey (type-level)", () => { + it("accepts keys already present on Context", () => { + defineLibraryKey("assets"); + defineLibraryKey("app"); + defineLibraryKey("vars"); + }); + + it("rejects keys that are not part of Context", () => { + // @ts-expect-error "unknown-key" is not a member of Context + defineLibraryKey("unknown-key"); + }); +}); diff --git a/packages/common/test/define-library-key.spec.ts b/packages/common/test/define-library-key.spec.ts new file mode 100644 index 00000000..e7a2f900 --- /dev/null +++ b/packages/common/test/define-library-key.spec.ts @@ -0,0 +1,9 @@ +import { describe, expect, it } from "vitest"; + +import { defineLibraryKey } from "../src"; + +describe("defineLibraryKey", () => { + it("returns the given key unchanged", () => { + expect(defineLibraryKey("assets")).toBe("assets"); + }); +}); diff --git a/packages/common/test/exceptions.spec.ts b/packages/common/test/exceptions.spec.ts index 4f82f289..36866bb9 100644 --- a/packages/common/test/exceptions.spec.ts +++ b/packages/common/test/exceptions.spec.ts @@ -1,6 +1,11 @@ import { describe, expect, it } from "vitest"; -import { NfConfigException, NfFetchException, NfNotFound, NfNotInitializedException } from "../src"; +import { + NfDuplicateLibraryException, + NfFetchException, + NfNotFound, + NfNotInitializedException, +} from "../src"; describe("NfNotInitializedException", () => { it("should have code 404", () => { @@ -78,28 +83,20 @@ describe("NfFetchException", () => { }); }); -describe("NfConfigException", () => { - it("should have code 400", () => { - expect(new NfConfigException("bad value").code).toBe(400); +describe("NfDuplicateLibraryException", () => { + it("should have code 409", () => { + expect(new NfDuplicateLibraryException("ecs").code).toBe(409); }); - it("should include message in output", () => { - expect(new NfConfigException("bad value").message).toContain("bad value"); - }); - - it("should include library name when provided", () => { - expect(new NfConfigException("bad value", "MyLib").message).toContain("(MyLib)"); - }); - - it("should omit library name when not provided", () => { - expect(new NfConfigException("bad value").message).not.toContain("("); + it("should include the key in message", () => { + expect(new NfDuplicateLibraryException("ecs").message).toContain('"ecs"'); }); it("should have [NANOFORGE] prefix", () => { - expect(new NfConfigException("bad value").message).toMatch(/^\[NANOFORGE]/); + expect(new NfDuplicateLibraryException("ecs").message).toMatch(/^\[NANOFORGE]/); }); it("should be an instance of Error", () => { - expect(new NfConfigException("bad value")).toBeInstanceOf(Error); + expect(new NfDuplicateLibraryException("ecs")).toBeInstanceOf(Error); }); }); diff --git a/packages/common/test/library.spec.ts b/packages/common/test/library.spec.ts index 9f8c3489..7c8900a3 100644 --- a/packages/common/test/library.spec.ts +++ b/packages/common/test/library.spec.ts @@ -1,103 +1,44 @@ -import { beforeEach, describe, expect, it } from "vitest"; +import { describe, expect, it } from "vitest"; -import { - LibraryContext, - LibraryHandle, - LibraryStatusEnum, - NfNotInitializedException, -} from "../src"; -import { Library } from "../src/library/libraries/library"; -import { BaseLibraryManager } from "../src/library/manager/managers/base-library.manager"; -import { RelationshipHandler } from "../src/library/relationship/relationship-handler"; +import { Library, NfNotInitializedException, defineLibraryKey } from "../src"; +import type { Context, InitContext } from "../src"; class TestLibrary extends Library { - private readonly _name: string; - - constructor(name = "TestLibrary", options?: ConstructorParameters[0]) { - super(options); - this._name = name; - } - - get __name(): string { - return this._name; - } + readonly key = defineLibraryKey("assets"); public expose_throwNotInitializedError(): never { return this.throwNotInitializedError(); } } -class TestableBaseLibraryManager extends BaseLibraryManager { - public expose_setNewLibrary(sym: symbol, library: TestLibrary, context: LibraryContext): void { - this.setNewLibrary(sym, library, context); - } -} - -describe("RelationshipHandler", () => { - it("should store dependencies", () => { - const dep = Symbol("dep"); - const handler = new RelationshipHandler([dep], [], []); - expect(handler.dependencies).toContain(dep); - }); - - it("should store runBefore", () => { - const before = Symbol("before"); - const handler = new RelationshipHandler([], [before], []); - expect(handler.runBefore).toContain(before); - }); - - it("should store runAfter", () => { - const after = Symbol("after"); - const handler = new RelationshipHandler([], [], [after]); - expect(handler.runAfter).toContain(after); - }); - - it("should return empty arrays when initialised with empty arrays", () => { - const handler = new RelationshipHandler([], [], []); - expect(handler.dependencies).toEqual([]); - expect(handler.runBefore).toEqual([]); - expect(handler.runAfter).toEqual([]); - }); - - it("should store multiple symbols", () => { - const a = Symbol("a"); - const b = Symbol("b"); - const handler = new RelationshipHandler([a, b], [], []); - expect(handler.dependencies).toEqual([a, b]); - }); -}); - describe("Library", () => { describe("defaults", () => { it("should have empty relationship arrays when no options are given", () => { const lib = new TestLibrary(); - expect(lib.__relationship.dependencies).toEqual([]); - expect(lib.__relationship.runBefore).toEqual([]); - expect(lib.__relationship.runAfter).toEqual([]); + expect(lib.relationships.dependencies).toEqual([]); + expect(lib.relationships.runBefore).toEqual([]); + expect(lib.relationships.runAfter).toEqual([]); }); - it("should expose the correct __name", () => { - expect(new TestLibrary("MyLib").__name).toBe("MyLib"); + it("should default expose() to undefined", () => { + expect(new TestLibrary().expose()).toBeUndefined(); }); }); describe("options", () => { it("should use partial dependencies option", () => { - const dep = Symbol("dep"); - const lib = new TestLibrary("TestLibrary", { dependencies: [dep] }); - expect(lib.__relationship.dependencies).toContain(dep); + const lib = new TestLibrary({ dependencies: ["other"] }); + expect(lib.relationships.dependencies).toEqual(["other"]); }); it("should use partial runBefore option", () => { - const before = Symbol("before"); - const lib = new TestLibrary("TestLibrary", { runBefore: [before] }); - expect(lib.__relationship.runBefore).toContain(before); + const lib = new TestLibrary({ runBefore: ["other"] }); + expect(lib.relationships.runBefore).toEqual(["other"]); }); it("should use partial runAfter option", () => { - const after = Symbol("after"); - const lib = new TestLibrary("TestLibrary", { runAfter: [after] }); - expect(lib.__relationship.runAfter).toContain(after); + const lib = new TestLibrary({ runAfter: ["other"] }); + expect(lib.relationships.runAfter).toEqual(["other"]); }); }); @@ -107,78 +48,23 @@ describe("Library", () => { expect(() => lib.expose_throwNotInitializedError()).toThrow(NfNotInitializedException); }); - it("should include the library name in the error message", () => { - const lib = new TestLibrary("MySpecialLib"); - expect(() => lib.expose_throwNotInitializedError()).toThrow(/MySpecialLib/); + it("should include the library key in the error message", () => { + const lib = new TestLibrary(); + expect(() => lib.expose_throwNotInitializedError()).toThrow(/assets/); }); }); - describe("__init and __clear", () => { + describe("__init, __run and __clear", () => { it("__init should resolve without error by default", async () => { - const lib = new TestLibrary(); - await expect(lib.__init({} as any)).resolves.toBeUndefined(); + await expect(new TestLibrary().__init({} as InitContext)).resolves.toBeUndefined(); }); - it("__clear should resolve without error by default", async () => { - const lib = new TestLibrary(); - await expect(lib.__clear({} as any)).resolves.toBeUndefined(); + it("__run should resolve without error by default", async () => { + await expect(new TestLibrary().__run({} as Context)).resolves.toBeUndefined(); }); - }); -}); - -describe("LibraryContext", () => { - it("should start with UNLOADED status", () => { - const ctx = new LibraryContext(); - expect(ctx.status).toBe(LibraryStatusEnum.UNLOADED); - }); -}); - -describe("LibraryHandle", () => { - it("should expose the symbol", () => { - const sym = Symbol("test"); - const handle = new LibraryHandle(sym, new TestLibrary(), new LibraryContext()); - expect(handle.symbol).toBe(sym); - }); - - it("should expose the library", () => { - const lib = new TestLibrary(); - const handle = new LibraryHandle(Symbol("test"), lib, new LibraryContext()); - expect(handle.library).toBe(lib); - }); - - it("should expose the context", () => { - const ctx = new LibraryContext(); - const handle = new LibraryHandle(Symbol("test"), new TestLibrary(), ctx); - expect(handle.context).toBe(ctx); - }); -}); -describe("BaseLibraryManager", () => { - let manager: TestableBaseLibraryManager; - - beforeEach(() => { - manager = new TestableBaseLibraryManager(); - }); - - it("should retrieve a library by symbol after setting it", () => { - const sym = Symbol.for("myLib"); - const lib = new TestLibrary(); - const ctx = new LibraryContext(); - - manager.expose_setNewLibrary(Symbol.for("filler"), new TestLibrary(), ctx); - manager.expose_setNewLibrary(sym, lib, ctx); - - const handle = manager.get(sym); - expect(handle.library).toBe(lib); - expect(handle.symbol).toBe(sym); - }); - - it("should throw when getting a library that was not set", () => { - const sym = Symbol.for("unknown"); - expect(() => manager.get(sym)).toThrow(); - }); - - it("should throw when getting a library by unknown index", () => { - expect(() => (manager as any)._get(99)).toThrow(); + it("__clear should resolve without error by default", async () => { + await expect(new TestLibrary().__clear({} as Context)).resolves.toBeUndefined(); + }); }); }); diff --git a/packages/common/tsconfig.spec.json b/packages/common/tsconfig.spec.json index 8270caba..bcc1ebcb 100644 --- a/packages/common/tsconfig.spec.json +++ b/packages/common/tsconfig.spec.json @@ -5,6 +5,6 @@ "noEmit": true, "skipLibCheck": true }, - "include": ["test/**/*.spec.ts"], + "include": ["test/**/*.spec.ts", "test/**/*.spec-d.ts"], "exclude": ["node_modules"] } diff --git a/packages/core-editor/.cliff-jumperrc.json b/packages/env/.cliff-jumperrc.json similarity index 75% rename from packages/core-editor/.cliff-jumperrc.json rename to packages/env/.cliff-jumperrc.json index fce3ee21..2f00502b 100644 --- a/packages/core-editor/.cliff-jumperrc.json +++ b/packages/env/.cliff-jumperrc.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "core-editor", + "name": "env", "org": "nanoforge-dev", - "packagePath": "packages/core-editor", + "packagePath": "packages/env", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/music/.gitignore b/packages/env/.gitignore similarity index 91% rename from packages/music/.gitignore rename to packages/env/.gitignore index e2764b6d..88ef62e8 100644 --- a/packages/music/.gitignore +++ b/packages/env/.gitignore @@ -12,40 +12,6 @@ # 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 @@ -257,8 +223,6 @@ dist .yarn/install-state.gz .pnp.* -### Private - # Turbo .turbo/ @@ -266,10 +230,5 @@ dist src/**/*.js src/**/*.d.ts -# pubilc directory -public/ -compile_commands.json -emsdk/ - # mint-tsdocs cache docs/.tsdocs/ diff --git a/packages/network-server/.prettierignore b/packages/env/.prettierignore similarity index 100% rename from packages/network-server/.prettierignore rename to packages/env/.prettierignore diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/packages/env/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/graphics-2d/LICENSE b/packages/env/LICENSE similarity index 97% rename from packages/graphics-2d/LICENSE rename to packages/env/LICENSE index 62c6400b..46724861 100644 --- a/packages/graphics-2d/LICENSE +++ b/packages/env/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/env/README.md b/packages/env/README.md new file mode 100644 index 00000000..799fc9b0 --- /dev/null +++ b/packages/env/README.md @@ -0,0 +1,123 @@ +
+
+

+ NanoForge +

+
+

+ npm version + npm downloads + Tests status + Last commit + Contributors +

+
+ +## About + +`@nanoforge-dev/env` is a wrapper around [class-validator][class-validator] and [class-transformer][class-transformer] used to validate and transform raw environment values (`InitContext.env`, `process.env`, …) into typed, decorated configuration classes. + +## Installation + +**Node.js 26 or newer is required.** + +```sh +npm install @nanoforge-dev/env +yarn add @nanoforge-dev/env +pnpm add @nanoforge-dev/env +bun add @nanoforge-dev/env +``` + +## Warning + +This library is intended for use by other NanoForge libraries and application code that reads environment configuration — it is not a library that consumers of `@nanoforge-dev/core` need to install standalone unless they are declaring their own environment-backed config classes. + +## Example usage + +Declare a configuration class decorated with `@nanoforge-dev/env`'s decorators: + +```ts +import { + Default, + Expose, + IsBoolean, + IsByteLength, + IsIpOrURL, + IsOptional, + IsPort, + TransformToBoolean, +} from "@nanoforge-dev/env"; + +export class ClientConfigNetwork { + // Optional port, but must be a valid port string when present. + @Expose() + @IsOptional() + @IsPort() + SERVER_TCP_PORT?: string; + + // Required — must be a valid IP address or URL. + @Expose() + @IsIpOrURL(undefined, undefined, { protocols: ["ws", "wss", "http", "https"] }) + SERVER_ADDRESS!: string; + + // Falls back to "PACKET_END" when absent. + @Expose() + @Default("PACKET_END") + @IsByteLength(2, 64) + MAGIC_VALUE!: string; + + // "true"/"false" string values are transformed into a native boolean. + @Expose() + @TransformToBoolean() + @IsBoolean() + @Default(false) + WSS!: boolean; +} +``` + +Then validate and populate an instance from a raw environment object with `registerEnv`: + +```ts +import { registerEnv } from "@nanoforge-dev/env"; + +import { ClientConfigNetwork } from "./config.client.network"; + +export class NetworkClientLibrary extends Library { + public override async __init(ctx: InitContext): Promise { + const config = await registerEnv(ClientConfigNetwork, ctx.env); + + // `config` is a fully validated, defaulted ClientConfigNetwork instance. + } +} +``` + +`registerEnv` throws `NfEnvValidationException` when the given environment doesn't satisfy the class's decorators. + +All of [class-validator][class-validator]'s decorators (`IsString`, `IsPort`, `IsOptional`, …) and `class-transformer`'s `@Expose`/`@Transform` are re-exported directly from this package, alongside `@nanoforge-dev/env`'s own additions: + +- `@Default(value)` — supplies a fallback when the property is `undefined`/`null`. +- `@IsIpOrURL(...)` — validates an IPv4/IPv6 address or a fully qualified domain name. +- `@TransformToBoolean()` — transforms the string `"true"`/`"false"` into a native boolean. + +## Links + +- [GitHub][source] +- [npm][npm] + +## Contributing + +Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the +[documentation][documentation]. +See [the contribution guide][contributing] if you'd like to submit a PR. + +## Help + +If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. + +[documentation]: https://github.com/NanoForge-dev/Engine +[discussions]: https://github.com/NanoForge-dev/Engine/discussions +[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/env +[npm]: https://www.npmjs.com/package/@nanoforge-dev/env +[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md +[class-validator]: https://github.com/typestack/class-validator +[class-transformer]: https://github.com/typestack/class-transformer diff --git a/packages/input/cliff.toml b/packages/env/cliff.toml similarity index 100% rename from packages/input/cliff.toml rename to packages/env/cliff.toml diff --git a/packages/network-client/eslint.config.js b/packages/env/eslint.config.js similarity index 100% rename from packages/network-client/eslint.config.js rename to packages/env/eslint.config.js diff --git a/packages/ecs-lib/mint-tsdocs.config.json b/packages/env/mint-tsdocs.config.json similarity index 82% rename from packages/ecs-lib/mint-tsdocs.config.json rename to packages/env/mint-tsdocs.config.json index c8a98897..debf79a4 100644 --- a/packages/ecs-lib/mint-tsdocs.config.json +++ b/packages/env/mint-tsdocs.config.json @@ -1,7 +1,7 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/ecs-lib", + "outputFolder": "../../docs/references/env", "lint": { "eslint": { "enabled": true diff --git a/packages/network-client/package.json b/packages/env/package.json similarity index 86% rename from packages/network-client/package.json rename to packages/env/package.json index f9ecf2c7..933a132a 100644 --- a/packages/network-client/package.json +++ b/packages/env/package.json @@ -1,8 +1,8 @@ { "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/network-client", + "name": "@nanoforge-dev/env", "version": "1.4.2", - "description": "NanoForge Engine - Network Client", + "description": "NanoForge Engine - Env", "keywords": [ "nanoforge", "game", @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -43,7 +44,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/network-client" + "directory": "packages/env" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -52,13 +53,14 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/network-client/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/env/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/config": "workspace:*" + "class-transformer": "catalog:config", + "class-validator": "catalog:config" }, "devDependencies": { "@favware/cliff-jumper": "catalog:ci", @@ -72,7 +74,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/music/prettier.config.js b/packages/env/prettier.config.js similarity index 100% rename from packages/music/prettier.config.js rename to packages/env/prettier.config.js diff --git a/packages/env/src/decorators/default.decorator.ts b/packages/env/src/decorators/default.decorator.ts new file mode 100644 index 00000000..3bbbea82 --- /dev/null +++ b/packages/env/src/decorators/default.decorator.ts @@ -0,0 +1,16 @@ +import { Transform } from "class-transformer"; +import type { TransformFnParams } from "class-transformer/types/interfaces/metadata/transform-fn-params.interface"; + +/** + * Property decorator that supplies a fallback value when the environment + * variable is `undefined` or `null`. + * + * @remarks + * Pairs with `class-transformer`'s `@Expose` and `class-validator` + * decorators. The default is deep-cloned via `JSON.parse(JSON.stringify(…))` + * so objects are not shared between instances. + * + * @param defaultValue - The value to use when the property is absent. + */ +export const Default = (defaultValue: unknown): PropertyDecorator => + Transform(({ value }: TransformFnParams) => value ?? JSON.parse(JSON.stringify(defaultValue))); diff --git a/packages/config/src/validators/is-ip-or-url.validator.ts b/packages/env/src/decorators/is-ip-or-url.decorator.ts similarity index 57% rename from packages/config/src/validators/is-ip-or-url.validator.ts rename to packages/env/src/decorators/is-ip-or-url.decorator.ts index d295eff9..6c1c0fc0 100644 --- a/packages/config/src/validators/is-ip-or-url.validator.ts +++ b/packages/env/src/decorators/is-ip-or-url.decorator.ts @@ -4,41 +4,24 @@ import { type ValidationOptions, isIP, isURL, registerDecorator } from "class-va * Property decorator that validates whether the value is a valid IPv4/IPv6 * address or a fully qualified domain name (URL). * - * @remarks - * Built on top of `class-validator`'s `isIP` and `isURL` helpers. Use on - * config properties that represent server hostnames or addresses. - * * @param validationOptions - Optional class-validator validation options. * @param isIPOptions - Optional options for `isIP` validation. * @param isURLOptions - Optional options for `isURL` validation. - * - * @example - * ```ts - * class MyConfig { - * \@Expose() - * \@IsIpOrURL() - * SERVER_ADDRESS!: string; - * } - * ``` */ export const IsIpOrURL = ( validationOptions?: ValidationOptions, isIPOptions?: Parameters[1], isURLOptions?: Parameters[1], -) => { - return (object: object, propertyName: string) => { +): PropertyDecorator => { + return (object: object, propertyName: string | symbol) => { registerDecorator({ target: object.constructor, - propertyName: propertyName, + propertyName: propertyName as string, ...(validationOptions ? { options: validationOptions } : {}), constraints: [], validator: { - validate(value: string) { - return isIP(value, isIPOptions) || isURL(value, isURLOptions); - }, - defaultMessage() { - return `$value must be a valid IP address or URL`; - }, + validate: (value: string) => isIP(value, isIPOptions) || isURL(value, isURLOptions), + defaultMessage: () => "$value must be a valid IP address or URL", }, }); }; diff --git a/packages/config/src/transformers/boolean.transformer.ts b/packages/env/src/decorators/transform-to-boolean.decorator.ts similarity index 55% rename from packages/config/src/transformers/boolean.transformer.ts rename to packages/env/src/decorators/transform-to-boolean.decorator.ts index a6ef7a80..64aae1ce 100644 --- a/packages/config/src/transformers/boolean.transformer.ts +++ b/packages/env/src/decorators/transform-to-boolean.decorator.ts @@ -1,6 +1,6 @@ import { Transform } from "class-transformer"; -const transformStringToBoolean = ({ value }: { value: string }) => { +const transformStringToBoolean = ({ value }: { value: string }): boolean | undefined => { if (value === "true") return true; if (value === "false") return false; return undefined; @@ -13,17 +13,6 @@ const transformStringToBoolean = ({ value }: { value: string }) => { * @remarks * Returns `undefined` for any value that is neither `"true"` nor `"false"`. * Pair with `@IsBoolean()` and `@Default(false)` for a fully validated and - * defaulted boolean config property. - * - * @example - * ```ts - * class MyConfig { - * \@Expose() - * \@TransformToBoolean() - * \@IsBoolean() - * \@Default(false) - * FEATURE_FLAG!: boolean; - * } - * ``` + * defaulted boolean property. */ -export const TransformToBoolean = () => Transform(transformStringToBoolean); +export const TransformToBoolean = (): PropertyDecorator => Transform(transformStringToBoolean); diff --git a/packages/config/src/exports/class-transformer.ts b/packages/env/src/exports/class-transformer.ts similarity index 100% rename from packages/config/src/exports/class-transformer.ts rename to packages/env/src/exports/class-transformer.ts diff --git a/packages/config/src/exports/class-validator.ts b/packages/env/src/exports/class-validator.ts similarity index 100% rename from packages/config/src/exports/class-validator.ts rename to packages/env/src/exports/class-validator.ts diff --git a/packages/env/src/index.ts b/packages/env/src/index.ts new file mode 100644 index 00000000..6f3b6b83 --- /dev/null +++ b/packages/env/src/index.ts @@ -0,0 +1,7 @@ +export * from "./decorators/default.decorator"; +export * from "./decorators/is-ip-or-url.decorator"; +export * from "./decorators/transform-to-boolean.decorator"; +export * from "./exports/class-transformer"; +export * from "./exports/class-validator"; +export * from "./registry/env-validation.exception"; +export * from "./registry/register-env"; diff --git a/packages/env/src/registry/env-validation.exception.ts b/packages/env/src/registry/env-validation.exception.ts new file mode 100644 index 00000000..2ab34ea1 --- /dev/null +++ b/packages/env/src/registry/env-validation.exception.ts @@ -0,0 +1,16 @@ +import { NfException } from "@nanoforge-dev/common"; +import type { ValidationError } from "class-validator"; + +/** + * Thrown by `registerEnv` when the given environment doesn't satisfy the + * target class's `class-validator` decorators. + */ +export class NfEnvValidationException extends NfException { + get code(): number { + return 400; + } + + constructor(errors: ValidationError[]) { + super(`Env validation failed: ${errors.toString()}`); + } +} diff --git a/packages/env/src/registry/register-env.ts b/packages/env/src/registry/register-env.ts new file mode 100644 index 00000000..eca95af1 --- /dev/null +++ b/packages/env/src/registry/register-env.ts @@ -0,0 +1,27 @@ +import { plainToInstance } from "class-transformer"; +import { validate } from "class-validator"; + +import { NfEnvValidationException } from "./env-validation.exception"; + +/** + * Validates a raw environment object against a `class-validator`-decorated + * class and returns a populated instance. + * + * @remarks + * Callable from anywhere — inside a library's own `__init(ctx)` (reading + * `ctx.env`), or from an app's `main.ts` before constructing the + * application. Not tied to `@nanoforge-dev/core` in any way. + * + * @param EnvClass - A class decorated with `class-validator`/`class-transformer` decorators. + * @param env - Raw, unvalidated environment values (e.g. `process.env` or `InitContext.env`). + * @throws `NfEnvValidationException` When validation fails. + */ +export const registerEnv = async ( + EnvClass: new () => T, + env: Record, +): Promise => { + const data = plainToInstance(EnvClass, env, { excludeExtraneousValues: true }); + const errors = await validate(data); + if (errors.length > 0) throw new NfEnvValidationException(errors); + return data; +}; diff --git a/packages/env/test/default.spec.ts b/packages/env/test/default.spec.ts new file mode 100644 index 00000000..60213feb --- /dev/null +++ b/packages/env/test/default.spec.ts @@ -0,0 +1,40 @@ +import { plainToInstance } from "class-transformer"; +import { describe, expect, it } from "vitest"; + +import { Default, Expose } from "../src"; + +class Fixture { + @Expose() + @Default("localhost") + HOST!: string; +} + +describe("Default", () => { + it("uses the given value when present", () => { + const instance = plainToInstance(Fixture, { HOST: "example.com" }); + expect(instance.HOST).toBe("example.com"); + }); + + it("falls back to the default when the value is undefined", () => { + const instance = plainToInstance(Fixture, {}); + expect(instance.HOST).toBe("localhost"); + }); + + it("falls back to the default when the value is null", () => { + const instance = plainToInstance(Fixture, { HOST: null }); + expect(instance.HOST).toBe("localhost"); + }); + + it("does not share object defaults between instances", () => { + class WithObjectDefault { + @Expose() + @Default({ count: 0 }) + opts!: { count: number }; + } + + const a = plainToInstance(WithObjectDefault, {}); + const b = plainToInstance(WithObjectDefault, {}); + a.opts.count = 5; + expect(b.opts.count).toBe(0); + }); +}); diff --git a/packages/env/test/is-ip-or-url.spec.ts b/packages/env/test/is-ip-or-url.spec.ts new file mode 100644 index 00000000..c99981b5 --- /dev/null +++ b/packages/env/test/is-ip-or-url.spec.ts @@ -0,0 +1,28 @@ +import { plainToInstance } from "class-transformer"; +import { validate } from "class-validator"; +import { describe, expect, it } from "vitest"; + +import { Expose, IsIpOrURL } from "../src"; + +class Fixture { + @Expose() + @IsIpOrURL() + ADDRESS!: string; +} + +describe("IsIpOrURL", () => { + it("accepts a valid IPv4 address", async () => { + const instance = plainToInstance(Fixture, { ADDRESS: "127.0.0.1" }); + expect(await validate(instance)).toHaveLength(0); + }); + + it("accepts a valid URL", async () => { + const instance = plainToInstance(Fixture, { ADDRESS: "example.com" }); + expect(await validate(instance)).toHaveLength(0); + }); + + it("rejects an invalid value", async () => { + const instance = plainToInstance(Fixture, { ADDRESS: "not a host!!" }); + expect(await validate(instance)).not.toHaveLength(0); + }); +}); diff --git a/packages/env/test/register-env.spec.ts b/packages/env/test/register-env.spec.ts new file mode 100644 index 00000000..144314dc --- /dev/null +++ b/packages/env/test/register-env.spec.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "vitest"; + +import { Expose, IsInt, IsString, NfEnvValidationException, registerEnv } from "../src"; + +class ServerEnv { + @Expose() + @IsString() + HOST!: string; + + @Expose() + @IsInt() + PORT!: number; +} + +describe("registerEnv", () => { + it("returns a populated, typed instance for valid env", async () => { + const config = await registerEnv(ServerEnv, { HOST: "localhost", PORT: 3000 }); + expect(config.HOST).toBe("localhost"); + expect(config.PORT).toBe(3000); + }); + + it("throws NfEnvValidationException for invalid env", async () => { + await expect( + registerEnv(ServerEnv, { HOST: "localhost", PORT: "not-a-number" }), + ).rejects.toThrow(NfEnvValidationException); + }); + + it("names the failing field in the error message", async () => { + await expect( + registerEnv(ServerEnv, { HOST: "localhost", PORT: "not-a-number" }), + ).rejects.toThrow(/PORT/); + }); +}); diff --git a/packages/env/test/transform-to-boolean.spec.ts b/packages/env/test/transform-to-boolean.spec.ts new file mode 100644 index 00000000..94c44239 --- /dev/null +++ b/packages/env/test/transform-to-boolean.spec.ts @@ -0,0 +1,25 @@ +import { plainToInstance } from "class-transformer"; +import { describe, expect, it } from "vitest"; + +import { Expose, TransformToBoolean } from "../src"; + +class Fixture { + @Expose() + @TransformToBoolean() + FLAG?: boolean; +} + +describe("TransformToBoolean", () => { + it("maps the string 'true' to true", () => { + expect(plainToInstance(Fixture, { FLAG: "true" }).FLAG).toBe(true); + }); + + it("maps the string 'false' to false", () => { + expect(plainToInstance(Fixture, { FLAG: "false" }).FLAG).toBe(false); + }); + + it("maps anything else to undefined", () => { + expect(plainToInstance(Fixture, { FLAG: "yes" }).FLAG).toBeUndefined(); + expect(plainToInstance(Fixture, {}).FLAG).toBeUndefined(); + }); +}); diff --git a/packages/music/tsconfig.json b/packages/env/tsconfig.json similarity index 100% rename from packages/music/tsconfig.json rename to packages/env/tsconfig.json diff --git a/packages/env/tsconfig.spec.json b/packages/env/tsconfig.spec.json new file mode 100644 index 00000000..8270caba --- /dev/null +++ b/packages/env/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "skipLibCheck": true + }, + "include": ["test/**/*.spec.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/input/tsdoc.json b/packages/env/tsdoc.json similarity index 100% rename from packages/input/tsdoc.json rename to packages/env/tsdoc.json diff --git a/packages/graphics-2d-editor/tsdown.config.ts b/packages/env/tsdown.config.ts similarity index 100% rename from packages/graphics-2d-editor/tsdown.config.ts rename to packages/env/tsdown.config.ts From eab54f749a4d058027d9fdc73c3fff7eb2c13d7e Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 11:51:27 +0200 Subject: [PATCH 07/12] feat: add new editor lib (#420) --- .../editor}/.cliff-jumperrc.json | 4 +- .../config => modules/editor}/.gitignore | 0 .../config => modules/editor}/.prettierignore | 0 modules/editor/CHANGELOG.md | 3 + .../core-editor => modules/editor}/LICENSE | 2 +- modules/editor/README.md | 102 +++++++++++ .../config => modules/editor}/cliff.toml | 0 .../editor}/eslint.config.js | 0 .../editor}/mint-tsdocs.config.json | 2 +- modules/editor/package.json | 91 ++++++++++ .../editor}/prettier.config.js | 0 modules/editor/src/context-augmentation.ts | 7 + modules/editor/src/editor-command.enum.ts | 19 ++ modules/editor/src/editor-context.type.ts | 18 ++ modules/editor/src/editor-library.ts | 70 ++++++++ modules/editor/src/event-emitter.ts | 47 +++++ modules/editor/src/index.ts | 6 + modules/editor/test/editor-library.spec.ts | 166 ++++++++++++++++++ modules/editor/test/event-emitter.spec.ts | 83 +++++++++ modules/editor/test/integration.spec.ts | 102 +++++++++++ .../config => modules/editor}/tsconfig.json | 0 .../editor}/tsconfig.spec.json | 0 .../config => modules/editor}/tsdoc.json | 0 .../editor}/tsdown.config.ts | 0 24 files changed, 718 insertions(+), 4 deletions(-) rename {packages/ecs-server => modules/editor}/.cliff-jumperrc.json (75%) rename {packages/config => modules/editor}/.gitignore (100%) rename {packages/config => modules/editor}/.prettierignore (100%) create mode 100644 modules/editor/CHANGELOG.md rename {packages/core-editor => modules/editor}/LICENSE (97%) create mode 100644 modules/editor/README.md rename {packages/config => modules/editor}/cliff.toml (100%) rename {packages/core-editor => modules/editor}/eslint.config.js (100%) rename {packages/config => modules/editor}/mint-tsdocs.config.json (82%) create mode 100644 modules/editor/package.json rename {packages/core-editor => modules/editor}/prettier.config.js (100%) create mode 100644 modules/editor/src/context-augmentation.ts create mode 100644 modules/editor/src/editor-command.enum.ts create mode 100644 modules/editor/src/editor-context.type.ts create mode 100644 modules/editor/src/editor-library.ts create mode 100644 modules/editor/src/event-emitter.ts create mode 100644 modules/editor/src/index.ts create mode 100644 modules/editor/test/editor-library.spec.ts create mode 100644 modules/editor/test/event-emitter.spec.ts create mode 100644 modules/editor/test/integration.spec.ts rename {packages/config => modules/editor}/tsconfig.json (100%) rename {packages/core-editor => modules/editor}/tsconfig.spec.json (100%) rename {packages/config => modules/editor}/tsdoc.json (100%) rename {packages/asset-manager => modules/editor}/tsdown.config.ts (100%) diff --git a/packages/ecs-server/.cliff-jumperrc.json b/modules/editor/.cliff-jumperrc.json similarity index 75% rename from packages/ecs-server/.cliff-jumperrc.json rename to modules/editor/.cliff-jumperrc.json index 7b287ca2..913d7626 100644 --- a/packages/ecs-server/.cliff-jumperrc.json +++ b/modules/editor/.cliff-jumperrc.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "ecs-server", + "name": "editor-lib", "org": "nanoforge-dev", - "packagePath": "packages/ecs-server", + "packagePath": "modules/editor", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/config/.gitignore b/modules/editor/.gitignore similarity index 100% rename from packages/config/.gitignore rename to modules/editor/.gitignore diff --git a/packages/config/.prettierignore b/modules/editor/.prettierignore similarity index 100% rename from packages/config/.prettierignore rename to modules/editor/.prettierignore diff --git a/modules/editor/CHANGELOG.md b/modules/editor/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/editor/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/core-editor/LICENSE b/modules/editor/LICENSE similarity index 97% rename from packages/core-editor/LICENSE rename to modules/editor/LICENSE index 62c6400b..46724861 100644 --- a/packages/core-editor/LICENSE +++ b/modules/editor/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/modules/editor/README.md b/modules/editor/README.md new file mode 100644 index 00000000..d03f9dc5 --- /dev/null +++ b/modules/editor/README.md @@ -0,0 +1,102 @@ +
+
+

+ NanoForge +

+
+

+ npm version + npm downloads + Tests status + Last commit + Contributors +

+
+ +## About + +`@nanoforge-dev/editor-lib` is the built-in bridge library between a running NanoForge application and an external editor host. It turns the raw `toEditor`/`fromEditor` event-emitter pair supplied via `RunOptions.editor` into the single, asymmetric `Context.editor` facade every other library sees. + +## Installation + +**Node.js 26 or newer is required.** + +```sh +npm install @nanoforge-dev/editor-lib +yarn add @nanoforge-dev/editor-lib +pnpm add @nanoforge-dev/editor-lib +bun add @nanoforge-dev/editor-lib +``` + +## Warning + +This library is opt-in — only register it when the app is started under an editor host (`app.use(new EditorLibrary())`). Without it, `Context.editor` is simply absent, and other libraries that check for it (like `@nanoforge-dev/ecs`'s hot-reload wiring) no-op cleanly. + +## Example usage + +Construct one `QueuedEventEmitter` per direction and hand both to `RunOptions.editor` when starting the app: + +```ts +import { QueuedEventEmitter } from "@nanoforge-dev/editor-lib"; + +const toEditor = new QueuedEventEmitter(); // engine -> editor +const fromEditor = new QueuedEventEmitter(); // editor -> engine + +await app.init({ + ...options, + editor: { toEditor, fromEditor }, +}); +``` + +Register `EditorLibrary` alongside your other libraries: + +```ts +import { EditorLibrary } from "@nanoforge-dev/editor-lib"; + +app.use(new EditorLibrary()); +``` + +Any registered library can then talk to the editor through `Context.editor`: + +```ts +public override async __run(ctx: Context): Promise { + ctx.editor?.emit("component-moved", entityId, position); +} +``` + +The editor host itself drives the other two operations directly on the raw emitters it created — sending commands via `fromEditor.emit(...)` and listening for outgoing notifications via `toEditor.on(...)` — which is why `Context.editor` only exposes `emit`/`on` for the reverse direction, not all four. + +## Base commands + +`EditorLibrary` handles three reserved editor → engine commands itself, with no app-side wiring required — they're forwarded straight to `Context.app`'s pause/resume/stop actions: + +```ts +import { EditorCommand } from "@nanoforge-dev/editor-lib"; + +fromEditor.emit(EditorCommand.Pause); // ctx.app.requestPause() +fromEditor.emit(EditorCommand.Resume); // ctx.app.requestResume() +fromEditor.emit(EditorCommand.Stop); // ctx.app.requestStop() +``` + +Because `EditorLibrary` drains `fromEditor` from `__events` (which keeps running even while paused), a queued `EditorCommand.Resume` always reaches the engine and lifts the pause — it isn't blocked behind the very pause it's meant to undo. + +## Links + +- [GitHub][source] +- [npm][npm] + +## Contributing + +Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the +[documentation][documentation]. +See [the contribution guide][contributing] if you'd like to submit a PR. + +## Help + +If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. + +[documentation]: https://github.com/NanoForge-dev/Engine +[discussions]: https://github.com/NanoForge-dev/Engine/discussions +[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/editor +[npm]: https://www.npmjs.com/package/@nanoforge-dev/editor-lib +[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/config/cliff.toml b/modules/editor/cliff.toml similarity index 100% rename from packages/config/cliff.toml rename to modules/editor/cliff.toml diff --git a/packages/core-editor/eslint.config.js b/modules/editor/eslint.config.js similarity index 100% rename from packages/core-editor/eslint.config.js rename to modules/editor/eslint.config.js diff --git a/packages/config/mint-tsdocs.config.json b/modules/editor/mint-tsdocs.config.json similarity index 82% rename from packages/config/mint-tsdocs.config.json rename to modules/editor/mint-tsdocs.config.json index d68b969c..86f12472 100644 --- a/packages/config/mint-tsdocs.config.json +++ b/modules/editor/mint-tsdocs.config.json @@ -1,7 +1,7 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/config", + "outputFolder": "../../docs/references/editor", "lint": { "eslint": { "enabled": true diff --git a/modules/editor/package.json b/modules/editor/package.json new file mode 100644 index 00000000..a3cf9c99 --- /dev/null +++ b/modules/editor/package.json @@ -0,0 +1,91 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "@nanoforge-dev/editor-lib", + "version": "1.4.2", + "description": "NanoForge Engine - Editor", + "keywords": [ + "nanoforge", + "game", + "engine" + ], + "homepage": "https://github.com/NanoForge-dev/Engine#readme", + "bugs": "https://github.com/NanoForge-dev/Engine/issues", + "license": "MIT", + "contributors": [ + "Bill ", + "Exelo ", + "Fexkoser ", + "Josephine ", + "Tchips " + ], + "files": [ + "dist" + ], + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.cts", + "exports": { + ".": { + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + }, + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "./package.json": "./package.json" + }, + "type": "module", + "directories": { + "lib": "src" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Engine.git", + "directory": "modules/editor" + }, + "funding": "https://github.com/NanoForge-dev/Engine?sponsor", + "scripts": { + "build": "tsc --noEmit && tsdown --config-loader unrun", + "lint": "prettier --check . && eslint --format=pretty src", + "format": "prettier --write . && eslint --fix --format=pretty src", + "test:unit": "vitest run --config ../../vitest.config.ts", + "prepack": "pnpm run build && pnpm run lint", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/editor/*'", + "release": "cliff-jumper", + "docs": "mint-tsdocs generate" + }, + "dependencies": { + "@nanoforge-dev/common": "workspace:*" + }, + "devDependencies": { + "@favware/cliff-jumper": "catalog:ci", + "@nanoforge-dev/core": "workspace:*", + "@nanoforge-dev/utils-eslint-config": "workspace:*", + "@nanoforge-dev/utils-prettier-config": "workspace:*", + "@trivago/prettier-plugin-sort-imports": "catalog:lint", + "eslint": "catalog:lint", + "prettier": "catalog:lint", + "tsdown": "catalog:build", + "typescript": "catalog:core", + "unrun": "catalog:build", + "vitest": "catalog:test" + }, + "packageManager": "pnpm@12.0.0", + "engines": { + "node": "26" + }, + "publishConfig": { + "access": "public" + }, + "lint-staged": { + "**": [ + "prettier --ignore-unknown --write" + ], + "src/**/*.ts": [ + "eslint --fix" + ] + } +} diff --git a/packages/core-editor/prettier.config.js b/modules/editor/prettier.config.js similarity index 100% rename from packages/core-editor/prettier.config.js rename to modules/editor/prettier.config.js diff --git a/modules/editor/src/context-augmentation.ts b/modules/editor/src/context-augmentation.ts new file mode 100644 index 00000000..eac63b2f --- /dev/null +++ b/modules/editor/src/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { EditorContextApi } from "./editor-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + editor: EditorContextApi; + } +} diff --git a/modules/editor/src/editor-command.enum.ts b/modules/editor/src/editor-command.enum.ts new file mode 100644 index 00000000..1c7bd06e --- /dev/null +++ b/modules/editor/src/editor-command.enum.ts @@ -0,0 +1,19 @@ +/** + * Reserved editor → engine command names that `EditorLibrary` handles + * itself, wired directly onto `Context.app`'s pause/resume/stop actions. + * + * @remarks + * An editor host can send these through the raw `fromEditor` emitter it + * created (see `RunOptions.editor`) without any app-side wiring — no other + * library needs to know about them. + * + * @example + * ```ts + * fromEditor.emit(EditorCommand.Pause); + * ``` + */ +export enum EditorCommand { + Pause = "pause", + Resume = "resume", + Stop = "stop", +} diff --git a/modules/editor/src/editor-context.type.ts b/modules/editor/src/editor-context.type.ts new file mode 100644 index 00000000..7aef3ccc --- /dev/null +++ b/modules/editor/src/editor-context.type.ts @@ -0,0 +1,18 @@ +/** + * Public surface of `EditorLibrary`, exposed on `Context.editor`. + * + * @remarks + * Deliberately asymmetric: `emit` only sends to the editor, `on` only + * listens for commands from the editor. `Context.editor` reaches every + * registered library, so it must not let arbitrary library code impersonate + * an editor command or eavesdrop on the outgoing channel — the reverse two + * operations (listening on the outgoing channel, emitting on the incoming + * one) are reserved for the external editor host, which holds its own + * direct reference to both raw emitters. + */ +export interface EditorContextApi { + /** Sends a notification to the editor (e.g. "a component moved"). */ + emit(event: string, ...args: unknown[]): void; + /** Listens for a command from the editor (e.g. "hot-reload"). */ + on(event: string, listener: (...args: unknown[]) => void): void; +} diff --git a/modules/editor/src/editor-library.ts b/modules/editor/src/editor-library.ts new file mode 100644 index 00000000..d9495740 --- /dev/null +++ b/modules/editor/src/editor-library.ts @@ -0,0 +1,70 @@ +import { + type Context, + type EventEmitter, + type InitContext, + Library, + defineLibraryKey, +} from "@nanoforge-dev/common"; + +import { EditorCommand } from "./editor-command.enum"; +import type { EditorContextApi } from "./editor-context.type"; + +/** + * Base editor bridge library. + * + * @remarks + * Opt-in — register it only when the app is started under an editor host + * (`app.use(new EditorLibrary())`), not a mandatory built-in like the asset + * library. Reads the raw `toEditor`/`fromEditor` emitter pair from + * `RunOptions.editor` (see `@nanoforge-dev/common`'s `RunOptions` + * augmentation) and transforms them into the single `Context.editor` facade + * every other library sees. + */ +export class EditorLibrary extends Library { + readonly key = defineLibraryKey("editor"); + + private _toEditor: EventEmitter | undefined; + private _fromEditor: EventEmitter | undefined; + private _baseCommandsWired = false; + + public override async __init(ctx: InitContext): Promise { + this._toEditor = ctx.editor?.toEditor; + this._fromEditor = ctx.editor?.fromEditor; + } + + /** + * Drains queued editor → engine commands every tick — via `__events`, not + * `__run`, so this keeps happening even while the app is paused. That's + * what lets a queued "resume" command actually reach and lift the pause; + * if this drained inside `__run` instead, a paused app could never + * process the very command that would unpause it. + * + * Also wires the base `EditorCommand.Pause`/`.Resume`/`.Stop` commands + * (once) directly onto `Context.app` — an editor host gets these three + * actions for free, with no app-side listener code required. + */ + public override async __events(ctx: Context): Promise { + if (!this._baseCommandsWired && this._fromEditor) { + this._fromEditor.on(EditorCommand.Pause, () => ctx.app.requestPause()); + this._fromEditor.on(EditorCommand.Resume, () => ctx.app.requestResume()); + this._fromEditor.on(EditorCommand.Stop, () => ctx.app.requestStop()); + this._baseCommandsWired = true; + } + this._fromEditor?.runEvents(); + } + + public override expose(): EditorContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + emit: (event, ...args) => { + if (!library._toEditor) library.throwNotInitializedError(); + library._toEditor?.emit(event, ...args); + }, + on: (event, listener) => { + if (!library._fromEditor) library.throwNotInitializedError(); + library._fromEditor?.on(event, listener); + }, + }; + } +} diff --git a/modules/editor/src/event-emitter.ts b/modules/editor/src/event-emitter.ts new file mode 100644 index 00000000..5d122d45 --- /dev/null +++ b/modules/editor/src/event-emitter.ts @@ -0,0 +1,47 @@ +import type { EventEmitter } from "@nanoforge-dev/common"; + +/** + * Default `EventEmitter` implementation. Construct one for each direction of + * an editor bridge (`toEditor`/`fromEditor`) and hand both to `RunOptions.editor`. + */ +export class QueuedEventEmitter< + Events extends string = string, + EventsMap extends Record = Record, +> implements EventEmitter { + private readonly listeners = new Map void)[]>(); + private readonly queue: { event: Events; args: EventsMap[Events] }[] = []; + + on(event: K, listener: (...args: EventsMap[K]) => void): void { + const list = this.listeners.get(event) ?? []; + list.push(listener as (...args: EventsMap[Events]) => void); + this.listeners.set(event, list); + } + + off(event: K, listener: (...args: EventsMap[K]) => void): void { + const list = this.listeners.get(event); + if (!list) return; + this.listeners.set( + event, + list.filter( + (registered) => registered !== (listener as (...args: EventsMap[Events]) => void), + ), + ); + } + + emit(event: K, ...args: EventsMap[K]): void { + this.queue.push({ event, args }); + } + + runEvents(): void { + const pending = this.queue.splice(0, this.queue.length); + for (const { event, args } of pending) { + for (const listener of this.listeners.get(event) ?? []) { + try { + listener(...args); + } catch (error) { + console.error(error); + } + } + } + } +} diff --git a/modules/editor/src/index.ts b/modules/editor/src/index.ts new file mode 100644 index 00000000..3672df5c --- /dev/null +++ b/modules/editor/src/index.ts @@ -0,0 +1,6 @@ +import "./context-augmentation"; + +export { EditorCommand } from "./editor-command.enum"; +export type { EditorContextApi } from "./editor-context.type"; +export { EditorLibrary } from "./editor-library"; +export { QueuedEventEmitter } from "./event-emitter"; diff --git a/modules/editor/test/editor-library.spec.ts b/modules/editor/test/editor-library.spec.ts new file mode 100644 index 00000000..e3f7fd3f --- /dev/null +++ b/modules/editor/test/editor-library.spec.ts @@ -0,0 +1,166 @@ +import type { AppContext, EventEmitter, InitContext } from "@nanoforge-dev/common"; +import { describe, expect, it, vi } from "vitest"; + +import { EditorCommand, EditorLibrary } from "../src"; + +const makeEmitter = (): EventEmitter => { + const listeners = new Map void)[]>(); + return { + on: vi.fn((event: string, listener: (...args: unknown[]) => void) => { + const list = listeners.get(event) ?? []; + list.push(listener); + listeners.set(event, list); + }), + off: vi.fn(), + emit: vi.fn((event: string, ...args: unknown[]) => { + for (const listener of listeners.get(event) ?? []) listener(...args); + }), + runEvents: vi.fn(), + }; +}; + +const makeInitContext = (editor?: InitContext["editor"]): InitContext => ({ + vars: { get: () => undefined, set: () => {} }, + env: {}, + files: new Map(), + ...(editor ? { editor } : {}), +}); + +const makeAppContext = (): AppContext => ({ + isRunning: true, + isPaused: false, + delta: 0, + tickRate: 60, + requestStop: vi.fn(), + requestPause: vi.fn(), + requestResume: vi.fn(), +}); + +describe("EditorLibrary", () => { + it("exposes the reserved 'editor' key", () => { + expect(new EditorLibrary().key).toBe("editor"); + }); + + it("expose().emit forwards to toEditor.emit, not fromEditor", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + lib.expose().emit("move-component", "e1", "Position", { x: 1, y: 2 }); + + expect(toEditor.emit).toHaveBeenCalledWith("move-component", "e1", "Position", { x: 1, y: 2 }); + expect(fromEditor.emit).not.toHaveBeenCalled(); + }); + + it("expose().on forwards to fromEditor.on, not toEditor", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + const handler = vi.fn(); + lib.expose().on("hot-reload", handler); + + expect(fromEditor.on).toHaveBeenCalledWith("hot-reload", handler); + expect(toEditor.on).not.toHaveBeenCalled(); + }); + + it("only exposes emit and on — the reverse two operations are not reachable", async () => { + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor: makeEmitter(), fromEditor: makeEmitter() })); + + expect(Object.keys(lib.expose())).toEqual(["emit", "on"]); + }); + + it("__events drains fromEditor's queue each tick — not __run, so it still runs while paused", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + await lib.__events({} as any); + + expect(fromEditor.runEvents).toHaveBeenCalledOnce(); + }); + + it("__events does not throw when no editor bridge was provided (non-editor runs)", async () => { + const lib = new EditorLibrary(); + await expect(lib.__init(makeInitContext())).resolves.toBeUndefined(); + await expect(lib.__events({} as any)).resolves.toBeUndefined(); + }); + + describe("base commands", () => { + it("wires EditorCommand.Pause/Resume/Stop to ctx.app once, on the first __events call", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const app = makeAppContext(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + await lib.__events({ app } as any); + await lib.__events({ app } as any); + + expect(fromEditor.on).toHaveBeenCalledTimes(3); + expect(fromEditor.on).toHaveBeenCalledWith(EditorCommand.Pause, expect.any(Function)); + expect(fromEditor.on).toHaveBeenCalledWith(EditorCommand.Resume, expect.any(Function)); + expect(fromEditor.on).toHaveBeenCalledWith(EditorCommand.Stop, expect.any(Function)); + }); + + it("EditorCommand.Pause calls ctx.app.requestPause", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const app = makeAppContext(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + await lib.__events({ app } as any); + fromEditor.emit(EditorCommand.Pause); + + expect(app.requestPause).toHaveBeenCalledOnce(); + expect(app.requestResume).not.toHaveBeenCalled(); + expect(app.requestStop).not.toHaveBeenCalled(); + }); + + it("EditorCommand.Resume calls ctx.app.requestResume", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const app = makeAppContext(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + await lib.__events({ app } as any); + fromEditor.emit(EditorCommand.Resume); + + expect(app.requestResume).toHaveBeenCalledOnce(); + }); + + it("EditorCommand.Stop calls ctx.app.requestStop", async () => { + const toEditor = makeEmitter(); + const fromEditor = makeEmitter(); + const app = makeAppContext(); + const lib = new EditorLibrary(); + await lib.__init(makeInitContext({ toEditor, fromEditor })); + + await lib.__events({ app } as any); + fromEditor.emit(EditorCommand.Stop); + + expect(app.requestStop).toHaveBeenCalledOnce(); + }); + + it("does not wire base commands when no editor bridge was provided", async () => { + const lib = new EditorLibrary(); + await lib.__init(makeInitContext()); + + await expect(lib.__events({ app: makeAppContext() } as any)).resolves.toBeUndefined(); + }); + }); + + it("expose().emit/on throw when no editor bridge was provided, like every other library's not-initialized guard", async () => { + const lib = new EditorLibrary(); + await lib.__init(makeInitContext()); + + expect(() => lib.expose().emit("x")).toThrow(); + expect(() => lib.expose().on("x", vi.fn())).toThrow(); + }); +}); diff --git a/modules/editor/test/event-emitter.spec.ts b/modules/editor/test/event-emitter.spec.ts new file mode 100644 index 00000000..f51a81b1 --- /dev/null +++ b/modules/editor/test/event-emitter.spec.ts @@ -0,0 +1,83 @@ +import { describe, expect, it, vi } from "vitest"; + +import { QueuedEventEmitter } from "../src"; + +describe("QueuedEventEmitter", () => { + it("does not invoke listeners synchronously on emit", () => { + const emitter = new QueuedEventEmitter<"ping", { ping: [] }>(); + const listener = vi.fn(); + emitter.on("ping", listener); + + emitter.emit("ping"); + + expect(listener).not.toHaveBeenCalled(); + }); + + it("invokes listeners with the emitted args once runEvents() is called", () => { + const emitter = new QueuedEventEmitter<"move", { move: [number, number] }>(); + const listener = vi.fn(); + emitter.on("move", listener); + + emitter.emit("move", 1, 2); + emitter.runEvents(); + + expect(listener).toHaveBeenCalledOnce(); + expect(listener).toHaveBeenCalledWith(1, 2); + }); + + it("supports multiple listeners for the same event", () => { + const emitter = new QueuedEventEmitter<"ping", { ping: [] }>(); + const a = vi.fn(); + const b = vi.fn(); + emitter.on("ping", a); + emitter.on("ping", b); + + emitter.emit("ping"); + emitter.runEvents(); + + expect(a).toHaveBeenCalledOnce(); + expect(b).toHaveBeenCalledOnce(); + }); + + it("off() removes a listener", () => { + const emitter = new QueuedEventEmitter<"ping", { ping: [] }>(); + const listener = vi.fn(); + emitter.on("ping", listener); + emitter.off("ping", listener); + + emitter.emit("ping"); + emitter.runEvents(); + + expect(listener).not.toHaveBeenCalled(); + }); + + it("drains the queue so events are not re-delivered on a later runEvents()", () => { + const emitter = new QueuedEventEmitter<"ping", { ping: [] }>(); + const listener = vi.fn(); + emitter.on("ping", listener); + + emitter.emit("ping"); + emitter.runEvents(); + emitter.runEvents(); + + expect(listener).toHaveBeenCalledOnce(); + }); + + it("catches a listener error so other listeners still run", () => { + const emitter = new QueuedEventEmitter<"ping", { ping: [] }>(); + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + const throwing = vi.fn(() => { + throw new Error("boom"); + }); + const ok = vi.fn(); + emitter.on("ping", throwing); + emitter.on("ping", ok); + + emitter.emit("ping"); + emitter.runEvents(); + + expect(ok).toHaveBeenCalledOnce(); + expect(errorSpy).toHaveBeenCalledOnce(); + errorSpy.mockRestore(); + }); +}); diff --git a/modules/editor/test/integration.spec.ts b/modules/editor/test/integration.spec.ts new file mode 100644 index 00000000..00f63d4e --- /dev/null +++ b/modules/editor/test/integration.spec.ts @@ -0,0 +1,102 @@ +import { type Context, Library } from "@nanoforge-dev/common"; +import { NanoforgeFactory } from "@nanoforge-dev/core"; +import { afterEach, describe, expect, it, vi } from "vitest"; + +import { EditorCommand, EditorLibrary, QueuedEventEmitter } from "../src"; + +class ProbeLibrary extends Library { + readonly key = "probe"; + public received: unknown[][] = []; + public capturedContext: Context | undefined; + private _wired = false; + + public override async __events(ctx: Context): Promise { + this.capturedContext = ctx; + } + + public override async __run(ctx: Context): Promise { + if (!this._wired && ctx.editor) { + ctx.editor.on("ping", (...args) => this.received.push(args)); + this._wired = true; + } + ctx.editor?.emit("pong"); + } +} + +describe("editor bridge integration with @nanoforge-dev/core", () => { + afterEach(() => { + vi.useRealTimers(); + }); + + it("wires RunOptions.editor through core's generic InitContext spread into ctx.editor for every library", async () => { + vi.useFakeTimers(); + + const toEditor = new QueuedEventEmitter(); + const fromEditor = new QueuedEventEmitter(); + const toEditorListener = vi.fn(); + toEditor.on("pong", toEditorListener); + + const server = NanoforgeFactory.createServer({ tickRate: 60 }); + const probe = new ProbeLibrary(); + server.use(new EditorLibrary()); + server.use(probe); + + await server.init({ files: new Map(), env: {}, editor: { toEditor, fromEditor } }); + await server.run(); + + await vi.advanceTimersByTimeAsync(1); + + toEditor.runEvents(); + expect(toEditorListener).toHaveBeenCalled(); + + fromEditor.emit("ping", "hello"); + await vi.advanceTimersByTimeAsync(50); + + expect(probe.received).toEqual([["hello"]]); + }); + + it("leaves ctx.editor undefined when the app isn't started under an editor host", async () => { + vi.useFakeTimers(); + + const server = NanoforgeFactory.createServer({ tickRate: 60 }); + const probe = new ProbeLibrary(); + server.use(probe); + + await server.init({ files: new Map(), env: {} }); + await server.run(); + await vi.advanceTimersByTimeAsync(1); + + expect(probe.received).toEqual([]); + }); + + it("EditorCommand.Pause/Resume/Stop reach Context.app with no app-side wiring required", async () => { + vi.useFakeTimers(); + + const toEditor = new QueuedEventEmitter(); + const fromEditor = new QueuedEventEmitter(); + + const server = NanoforgeFactory.createServer({ tickRate: 1000 }); + const probe = new ProbeLibrary(); + server.use(new EditorLibrary()); + server.use(probe); + + await server.init({ files: new Map(), env: {}, editor: { toEditor, fromEditor } }); + await server.run(); + await vi.advanceTimersByTimeAsync(10); + + fromEditor.emit(EditorCommand.Pause); + await vi.advanceTimersByTimeAsync(10); + + expect(probe.capturedContext!.app.isPaused).toBe(true); + + fromEditor.emit(EditorCommand.Resume); + await vi.advanceTimersByTimeAsync(10); + + expect(probe.capturedContext!.app.isPaused).toBe(false); + + fromEditor.emit(EditorCommand.Stop); + await vi.advanceTimersByTimeAsync(10); + + expect(probe.capturedContext!.app.isRunning).toBe(false); + }); +}); diff --git a/packages/config/tsconfig.json b/modules/editor/tsconfig.json similarity index 100% rename from packages/config/tsconfig.json rename to modules/editor/tsconfig.json diff --git a/packages/core-editor/tsconfig.spec.json b/modules/editor/tsconfig.spec.json similarity index 100% rename from packages/core-editor/tsconfig.spec.json rename to modules/editor/tsconfig.spec.json diff --git a/packages/config/tsdoc.json b/modules/editor/tsdoc.json similarity index 100% rename from packages/config/tsdoc.json rename to modules/editor/tsdoc.json diff --git a/packages/asset-manager/tsdown.config.ts b/modules/editor/tsdown.config.ts similarity index 100% rename from packages/asset-manager/tsdown.config.ts rename to modules/editor/tsdown.config.ts From cb58db33c9b562c5d925f87dbb8867975944bfa6 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 11:51:57 +0200 Subject: [PATCH 08/12] refactor: change ecs to only one module (#417) * chore: remove unused .idea * feat: add new ecs --- .../ecs-lib => modules/ecs}/.clang-format | 0 .../ecs}/.cliff-jumperrc.json | 4 +- .../ecs-server => modules/ecs}/.gitignore | 4 + .../ecs}/.prettierignore | 2 +- modules/ecs/CHANGELOG.md | 3 + {packages/config => modules/ecs}/LICENSE | 2 +- modules/ecs/Makefile | 61 +++++++ modules/ecs/README.md | 92 ++++++++++ .../lib => modules/ecs/build}/libecs.d.ts | 2 +- .../ecs-lib => modules/ecs}/build/pre.ts | 2 +- .../asset-manager => modules/ecs}/cliff.toml | 0 .../config => modules/ecs}/eslint.config.js | 0 .../ecs}/mint-tsdocs.config.json | 4 +- .../ecs-client => modules/ecs}/package.json | 51 +++--- .../config => modules/ecs}/prettier.config.js | 0 modules/ecs/src/client/index.ts | 13 ++ modules/ecs/src/server/index.ts | 13 ++ .../ecs/src/shared/context-augmentation.ts | 7 + modules/ecs/src/shared/ecs-context.type.ts | 7 + modules/ecs/src/shared/ecs-library.ts | 74 ++++++++ modules/ecs/test/client/ecs-client.spec.ts | 148 +++++++++++++++ modules/ecs/test/server/ecs-server.spec.ts | 148 +++++++++++++++ .../ecs}/tsconfig.json | 0 .../ecs}/tsconfig.spec.json | 0 .../asset-manager => modules/ecs}/tsdoc.json | 0 modules/ecs/tsdown.config.ts | 6 + .../ecs-lib => modules/ecs}/wasm/Entity.cpp | 2 +- .../ecs-lib => modules/ecs}/wasm/Entity.hpp | 2 +- .../ecs-lib => modules/ecs}/wasm/Registry.cpp | 2 +- .../ecs-lib => modules/ecs}/wasm/Registry.hpp | 2 +- .../ecs}/wasm/SparseArray.cpp | 2 +- .../ecs}/wasm/SparseArray.hpp | 2 +- .../ecs-lib => modules/ecs}/wasm/Utils.cpp | 2 +- .../ecs-lib => modules/ecs}/wasm/Utils.hpp | 2 +- packages/asset-manager/.idea/.gitignore | 8 - packages/asset-manager/.idea/.name | 1 - .../[NanoForge] Engine Asset Manager.iml | 12 -- .../.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/asset-manager/.idea/editor.xml | 106 ----------- .../asset-manager/.idea/git_toolbox_blame.xml | 6 - .../asset-manager/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 12 -- .../asset-manager/.idea/jsLinters/eslint.xml | 6 - packages/asset-manager/.idea/misc.xml | 24 --- packages/asset-manager/.idea/modules.xml | 8 - packages/asset-manager/.idea/prettier.xml | 7 - packages/asset-manager/.idea/vcs.xml | 6 - packages/common/.idea/.gitignore | 8 - packages/common/.idea/.name | 1 - .../.idea/[NanoForge] Engine Common.iml | 12 -- packages/common/.idea/codeStyles/Project.xml | 57 ------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/common/.idea/git_toolbox_blame.xml | 6 - packages/common/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 6 - packages/common/.idea/jsLinters/eslint.xml | 6 - packages/common/.idea/modules.xml | 8 - packages/common/.idea/prettier.xml | 7 - packages/common/.idea/vcs.xml | 6 - packages/config/.idea/.gitignore | 8 - packages/config/.idea/.name | 1 - .../.idea/[NanoForge] Engine Config.iml | 12 -- packages/config/.idea/codeStyles/Project.xml | 57 ------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/config/.idea/git_toolbox_blame.xml | 6 - packages/config/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 6 - packages/config/.idea/jsLinters/eslint.xml | 6 - packages/config/.idea/modules.xml | 8 - packages/config/.idea/prettier.xml | 7 - packages/config/.idea/vcs.xml | 6 - packages/core-editor/.idea/.name | 1 - .../.idea/[NanoForge] Engine Core Editor.iml | 12 -- .../core-editor/.idea/codeStyles/Project.xml | 57 ------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - .../core-editor/.idea/git_toolbox_blame.xml | 6 - .../core-editor/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 6 - .../core-editor/.idea/jsLinters/eslint.xml | 6 - packages/core-editor/.idea/modules.xml | 8 - packages/core-editor/.idea/prettier.xml | 7 - packages/core-editor/.idea/vcs.xml | 6 - packages/core/.idea/.name | 1 - .../core/.idea/[NanoForge] Engine Core.iml | 12 -- packages/core/.idea/codeStyles/Project.xml | 57 ------ .../core/.idea/codeStyles/codeStyleConfig.xml | 5 - packages/core/.idea/git_toolbox_blame.xml | 6 - packages/core/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 6 - packages/core/.idea/jsLinters/eslint.xml | 6 - packages/core/.idea/modules.xml | 8 - packages/core/.idea/prettier.xml | 7 - packages/core/.idea/vcs.xml | 6 - packages/ecs-client/.idea/.gitignore | 8 - packages/ecs-client/.idea/.name | 1 - .../.idea/[NanoForge] Engine ECS Client.iml | 12 -- .../ecs-client/.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/ecs-client/.idea/editor.xml | 107 ----------- .../ecs-client/.idea/git_toolbox_blame.xml | 6 - packages/ecs-client/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 13 -- packages/ecs-client/.idea/misc.xml | 24 --- packages/ecs-client/.idea/modules.xml | 8 - packages/ecs-client/.idea/prettier.xml | 6 - packages/ecs-client/.idea/vcs.xml | 6 - packages/ecs-lib/.idea/.gitignore | 8 - packages/ecs-lib/.idea/.name | 1 - .../.idea/[NanoForge] Engine ECS Lib.iml | 12 -- packages/ecs-lib/.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/ecs-lib/.idea/editor.xml | 107 ----------- packages/ecs-lib/.idea/git_toolbox_blame.xml | 6 - packages/ecs-lib/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 13 -- packages/ecs-lib/.idea/misc.xml | 24 --- packages/ecs-lib/.idea/modules.xml | 8 - packages/ecs-lib/.idea/prettier.xml | 6 - packages/ecs-lib/.idea/vcs.xml | 6 - packages/ecs-server/.idea/.gitignore | 8 - packages/ecs-server/.idea/.name | 1 - .../.idea/[NanoForge] Engine ECS Server.iml | 12 -- .../ecs-server/.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/ecs-server/.idea/editor.xml | 107 ----------- .../ecs-server/.idea/git_toolbox_blame.xml | 6 - packages/ecs-server/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 13 -- packages/ecs-server/.idea/misc.xml | 24 --- packages/ecs-server/.idea/modules.xml | 8 - packages/ecs-server/.idea/prettier.xml | 6 - packages/ecs-server/.idea/vcs.xml | 6 - packages/graphics-2d-editor/.idea/.gitignore | 8 - packages/graphics-2d-editor/.idea/.name | 1 - .../[NanoForge] Engine Graphics 2D Editor.iml | 12 -- .../.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/graphics-2d-editor/.idea/editor.xml | 107 ----------- .../.idea/git_toolbox_blame.xml | 6 - .../.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 12 -- .../.idea/jsLinters/eslint.xml | 6 - packages/graphics-2d-editor/.idea/misc.xml | 24 --- packages/graphics-2d-editor/.idea/modules.xml | 8 - .../graphics-2d-editor/.idea/prettier.xml | 7 - packages/graphics-2d-editor/.idea/vcs.xml | 6 - packages/graphics-2d/.idea/.gitignore | 8 - packages/graphics-2d/.idea/.name | 1 - .../.idea/[NanoForge] Engine Graphics 2D.iml | 12 -- .../graphics-2d/.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/graphics-2d/.idea/editor.xml | 107 ----------- .../graphics-2d/.idea/git_toolbox_blame.xml | 6 - .../graphics-2d/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 12 -- .../graphics-2d/.idea/jsLinters/eslint.xml | 6 - packages/graphics-2d/.idea/misc.xml | 24 --- packages/graphics-2d/.idea/modules.xml | 8 - packages/graphics-2d/.idea/prettier.xml | 7 - packages/graphics-2d/.idea/vcs.xml | 6 - packages/input/.idea/.gitignore | 8 - packages/input/.idea/.name | 1 - .../input/.idea/[NanoForge] Engine Input.iml | 12 -- packages/input/.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/input/.idea/editor.xml | 106 ----------- packages/input/.idea/git_toolbox_blame.xml | 6 - packages/input/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 12 -- packages/input/.idea/jsLinters/eslint.xml | 6 - packages/input/.idea/misc.xml | 24 --- packages/input/.idea/modules.xml | 8 - packages/input/.idea/prettier.xml | 7 - packages/input/.idea/vcs.xml | 6 - packages/network-client/.idea/.gitignore | 8 - packages/network-client/.idea/.name | 1 - .../[NanoForge] Engine Network Client.iml | 12 -- .../.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/network-client/.idea/editor.xml | 107 ----------- .../.idea/git_toolbox_blame.xml | 6 - .../network-client/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 12 -- .../network-client/.idea/jsLinters/eslint.xml | 6 - packages/network-client/.idea/misc.xml | 24 --- packages/network-client/.idea/modules.xml | 8 - packages/network-client/.idea/prettier.xml | 7 - packages/network-client/.idea/vcs.xml | 6 - packages/network-server/.idea/.gitignore | 8 - packages/network-server/.idea/.name | 1 - .../[NanoForge] Engine Network Server.iml | 12 -- .../.idea/codeStyles/Project.xml | 172 ------------------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - packages/network-server/.idea/editor.xml | 107 ----------- .../.idea/git_toolbox_blame.xml | 6 - .../network-server/.idea/git_toolbox_prj.xml | 15 -- .../inspectionProfiles/Project_Default.xml | 12 -- .../network-server/.idea/jsLinters/eslint.xml | 6 - packages/network-server/.idea/misc.xml | 24 --- packages/network-server/.idea/modules.xml | 8 - packages/network-server/.idea/prettier.xml | 7 - packages/network-server/.idea/vcs.xml | 6 - 203 files changed, 620 insertions(+), 4052 deletions(-) rename {packages/ecs-lib => modules/ecs}/.clang-format (100%) rename {packages/config => modules/ecs}/.cliff-jumperrc.json (78%) rename {packages/ecs-server => modules/ecs}/.gitignore (98%) rename {packages/ecs-server => modules/ecs}/.prettierignore (95%) create mode 100644 modules/ecs/CHANGELOG.md rename {packages/config => modules/ecs}/LICENSE (97%) create mode 100644 modules/ecs/Makefile create mode 100644 modules/ecs/README.md rename {packages/ecs-lib/lib => modules/ecs/build}/libecs.d.ts (97%) rename {packages/ecs-lib => modules/ecs}/build/pre.ts (70%) rename {packages/asset-manager => modules/ecs}/cliff.toml (100%) rename {packages/config => modules/ecs}/eslint.config.js (100%) rename {packages/ecs-server => modules/ecs}/mint-tsdocs.config.json (69%) rename {packages/ecs-client => modules/ecs}/package.json (68%) rename {packages/config => modules/ecs}/prettier.config.js (100%) create mode 100644 modules/ecs/src/client/index.ts create mode 100644 modules/ecs/src/server/index.ts create mode 100644 modules/ecs/src/shared/context-augmentation.ts create mode 100644 modules/ecs/src/shared/ecs-context.type.ts create mode 100644 modules/ecs/src/shared/ecs-library.ts create mode 100644 modules/ecs/test/client/ecs-client.spec.ts create mode 100644 modules/ecs/test/server/ecs-server.spec.ts rename {packages/asset-manager => modules/ecs}/tsconfig.json (100%) rename {packages/asset-manager => modules/ecs}/tsconfig.spec.json (100%) rename {packages/asset-manager => modules/ecs}/tsdoc.json (100%) create mode 100644 modules/ecs/tsdown.config.ts rename {packages/ecs-lib => modules/ecs}/wasm/Entity.cpp (95%) rename {packages/ecs-lib => modules/ecs}/wasm/Entity.hpp (97%) rename {packages/ecs-lib => modules/ecs}/wasm/Registry.cpp (98%) rename {packages/ecs-lib => modules/ecs}/wasm/Registry.hpp (99%) rename {packages/ecs-lib => modules/ecs}/wasm/SparseArray.cpp (98%) rename {packages/ecs-lib => modules/ecs}/wasm/SparseArray.hpp (99%) rename {packages/ecs-lib => modules/ecs}/wasm/Utils.cpp (97%) rename {packages/ecs-lib => modules/ecs}/wasm/Utils.hpp (96%) delete mode 100644 packages/asset-manager/.idea/.gitignore delete mode 100644 packages/asset-manager/.idea/.name delete mode 100644 packages/asset-manager/.idea/[NanoForge] Engine Asset Manager.iml delete mode 100644 packages/asset-manager/.idea/codeStyles/Project.xml delete mode 100644 packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/asset-manager/.idea/editor.xml delete mode 100644 packages/asset-manager/.idea/git_toolbox_blame.xml delete mode 100644 packages/asset-manager/.idea/git_toolbox_prj.xml delete mode 100644 packages/asset-manager/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/asset-manager/.idea/jsLinters/eslint.xml delete mode 100644 packages/asset-manager/.idea/misc.xml delete mode 100644 packages/asset-manager/.idea/modules.xml delete mode 100644 packages/asset-manager/.idea/prettier.xml delete mode 100644 packages/asset-manager/.idea/vcs.xml delete mode 100644 packages/common/.idea/.gitignore delete mode 100644 packages/common/.idea/.name delete mode 100644 packages/common/.idea/[NanoForge] Engine Common.iml delete mode 100644 packages/common/.idea/codeStyles/Project.xml delete mode 100644 packages/common/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/common/.idea/git_toolbox_blame.xml delete mode 100644 packages/common/.idea/git_toolbox_prj.xml delete mode 100644 packages/common/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/common/.idea/jsLinters/eslint.xml delete mode 100644 packages/common/.idea/modules.xml delete mode 100644 packages/common/.idea/prettier.xml delete mode 100644 packages/common/.idea/vcs.xml delete mode 100644 packages/config/.idea/.gitignore delete mode 100644 packages/config/.idea/.name delete mode 100644 packages/config/.idea/[NanoForge] Engine Config.iml delete mode 100644 packages/config/.idea/codeStyles/Project.xml delete mode 100644 packages/config/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/config/.idea/git_toolbox_blame.xml delete mode 100644 packages/config/.idea/git_toolbox_prj.xml delete mode 100644 packages/config/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/config/.idea/jsLinters/eslint.xml delete mode 100644 packages/config/.idea/modules.xml delete mode 100644 packages/config/.idea/prettier.xml delete mode 100644 packages/config/.idea/vcs.xml delete mode 100644 packages/core-editor/.idea/.name delete mode 100644 packages/core-editor/.idea/[NanoForge] Engine Core Editor.iml delete mode 100644 packages/core-editor/.idea/codeStyles/Project.xml delete mode 100644 packages/core-editor/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/core-editor/.idea/git_toolbox_blame.xml delete mode 100644 packages/core-editor/.idea/git_toolbox_prj.xml delete mode 100644 packages/core-editor/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/core-editor/.idea/jsLinters/eslint.xml delete mode 100644 packages/core-editor/.idea/modules.xml delete mode 100644 packages/core-editor/.idea/prettier.xml delete mode 100644 packages/core-editor/.idea/vcs.xml delete mode 100644 packages/core/.idea/.name delete mode 100644 packages/core/.idea/[NanoForge] Engine Core.iml delete mode 100644 packages/core/.idea/codeStyles/Project.xml delete mode 100644 packages/core/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/core/.idea/git_toolbox_blame.xml delete mode 100644 packages/core/.idea/git_toolbox_prj.xml delete mode 100644 packages/core/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/core/.idea/jsLinters/eslint.xml delete mode 100644 packages/core/.idea/modules.xml delete mode 100644 packages/core/.idea/prettier.xml delete mode 100644 packages/core/.idea/vcs.xml delete mode 100644 packages/ecs-client/.idea/.gitignore delete mode 100644 packages/ecs-client/.idea/.name delete mode 100644 packages/ecs-client/.idea/[NanoForge] Engine ECS Client.iml delete mode 100644 packages/ecs-client/.idea/codeStyles/Project.xml delete mode 100644 packages/ecs-client/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/ecs-client/.idea/editor.xml delete mode 100644 packages/ecs-client/.idea/git_toolbox_blame.xml delete mode 100644 packages/ecs-client/.idea/git_toolbox_prj.xml delete mode 100644 packages/ecs-client/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/ecs-client/.idea/misc.xml delete mode 100644 packages/ecs-client/.idea/modules.xml delete mode 100644 packages/ecs-client/.idea/prettier.xml delete mode 100644 packages/ecs-client/.idea/vcs.xml delete mode 100644 packages/ecs-lib/.idea/.gitignore delete mode 100644 packages/ecs-lib/.idea/.name delete mode 100644 packages/ecs-lib/.idea/[NanoForge] Engine ECS Lib.iml delete mode 100644 packages/ecs-lib/.idea/codeStyles/Project.xml delete mode 100644 packages/ecs-lib/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/ecs-lib/.idea/editor.xml delete mode 100644 packages/ecs-lib/.idea/git_toolbox_blame.xml delete mode 100644 packages/ecs-lib/.idea/git_toolbox_prj.xml delete mode 100644 packages/ecs-lib/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/ecs-lib/.idea/misc.xml delete mode 100644 packages/ecs-lib/.idea/modules.xml delete mode 100644 packages/ecs-lib/.idea/prettier.xml delete mode 100644 packages/ecs-lib/.idea/vcs.xml delete mode 100644 packages/ecs-server/.idea/.gitignore delete mode 100644 packages/ecs-server/.idea/.name delete mode 100644 packages/ecs-server/.idea/[NanoForge] Engine ECS Server.iml delete mode 100644 packages/ecs-server/.idea/codeStyles/Project.xml delete mode 100644 packages/ecs-server/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/ecs-server/.idea/editor.xml delete mode 100644 packages/ecs-server/.idea/git_toolbox_blame.xml delete mode 100644 packages/ecs-server/.idea/git_toolbox_prj.xml delete mode 100644 packages/ecs-server/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/ecs-server/.idea/misc.xml delete mode 100644 packages/ecs-server/.idea/modules.xml delete mode 100644 packages/ecs-server/.idea/prettier.xml delete mode 100644 packages/ecs-server/.idea/vcs.xml delete mode 100644 packages/graphics-2d-editor/.idea/.gitignore delete mode 100644 packages/graphics-2d-editor/.idea/.name delete mode 100644 packages/graphics-2d-editor/.idea/[NanoForge] Engine Graphics 2D Editor.iml delete mode 100644 packages/graphics-2d-editor/.idea/codeStyles/Project.xml delete mode 100644 packages/graphics-2d-editor/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/graphics-2d-editor/.idea/editor.xml delete mode 100644 packages/graphics-2d-editor/.idea/git_toolbox_blame.xml delete mode 100644 packages/graphics-2d-editor/.idea/git_toolbox_prj.xml delete mode 100644 packages/graphics-2d-editor/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/graphics-2d-editor/.idea/jsLinters/eslint.xml delete mode 100644 packages/graphics-2d-editor/.idea/misc.xml delete mode 100644 packages/graphics-2d-editor/.idea/modules.xml delete mode 100644 packages/graphics-2d-editor/.idea/prettier.xml delete mode 100644 packages/graphics-2d-editor/.idea/vcs.xml delete mode 100644 packages/graphics-2d/.idea/.gitignore delete mode 100644 packages/graphics-2d/.idea/.name delete mode 100644 packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml delete mode 100644 packages/graphics-2d/.idea/codeStyles/Project.xml delete mode 100644 packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/graphics-2d/.idea/editor.xml delete mode 100644 packages/graphics-2d/.idea/git_toolbox_blame.xml delete mode 100644 packages/graphics-2d/.idea/git_toolbox_prj.xml delete mode 100644 packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/graphics-2d/.idea/jsLinters/eslint.xml delete mode 100644 packages/graphics-2d/.idea/misc.xml delete mode 100644 packages/graphics-2d/.idea/modules.xml delete mode 100644 packages/graphics-2d/.idea/prettier.xml delete mode 100644 packages/graphics-2d/.idea/vcs.xml delete mode 100644 packages/input/.idea/.gitignore delete mode 100644 packages/input/.idea/.name delete mode 100644 packages/input/.idea/[NanoForge] Engine Input.iml delete mode 100644 packages/input/.idea/codeStyles/Project.xml delete mode 100644 packages/input/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/input/.idea/editor.xml delete mode 100644 packages/input/.idea/git_toolbox_blame.xml delete mode 100644 packages/input/.idea/git_toolbox_prj.xml delete mode 100644 packages/input/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/input/.idea/jsLinters/eslint.xml delete mode 100644 packages/input/.idea/misc.xml delete mode 100644 packages/input/.idea/modules.xml delete mode 100644 packages/input/.idea/prettier.xml delete mode 100644 packages/input/.idea/vcs.xml delete mode 100644 packages/network-client/.idea/.gitignore delete mode 100644 packages/network-client/.idea/.name delete mode 100644 packages/network-client/.idea/[NanoForge] Engine Network Client.iml delete mode 100644 packages/network-client/.idea/codeStyles/Project.xml delete mode 100644 packages/network-client/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/network-client/.idea/editor.xml delete mode 100644 packages/network-client/.idea/git_toolbox_blame.xml delete mode 100644 packages/network-client/.idea/git_toolbox_prj.xml delete mode 100644 packages/network-client/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/network-client/.idea/jsLinters/eslint.xml delete mode 100644 packages/network-client/.idea/misc.xml delete mode 100644 packages/network-client/.idea/modules.xml delete mode 100644 packages/network-client/.idea/prettier.xml delete mode 100644 packages/network-client/.idea/vcs.xml delete mode 100644 packages/network-server/.idea/.gitignore delete mode 100644 packages/network-server/.idea/.name delete mode 100644 packages/network-server/.idea/[NanoForge] Engine Network Server.iml delete mode 100644 packages/network-server/.idea/codeStyles/Project.xml delete mode 100644 packages/network-server/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 packages/network-server/.idea/editor.xml delete mode 100644 packages/network-server/.idea/git_toolbox_blame.xml delete mode 100644 packages/network-server/.idea/git_toolbox_prj.xml delete mode 100644 packages/network-server/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 packages/network-server/.idea/jsLinters/eslint.xml delete mode 100644 packages/network-server/.idea/misc.xml delete mode 100644 packages/network-server/.idea/modules.xml delete mode 100644 packages/network-server/.idea/prettier.xml delete mode 100644 packages/network-server/.idea/vcs.xml diff --git a/packages/ecs-lib/.clang-format b/modules/ecs/.clang-format similarity index 100% rename from packages/ecs-lib/.clang-format rename to modules/ecs/.clang-format diff --git a/packages/config/.cliff-jumperrc.json b/modules/ecs/.cliff-jumperrc.json similarity index 78% rename from packages/config/.cliff-jumperrc.json rename to modules/ecs/.cliff-jumperrc.json index ce77165a..c3a0e115 100644 --- a/packages/config/.cliff-jumperrc.json +++ b/modules/ecs/.cliff-jumperrc.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", - "name": "config", + "name": "ecs", "org": "nanoforge-dev", - "packagePath": "packages/config", + "packagePath": "modules/ecs", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/ecs-server/.gitignore b/modules/ecs/.gitignore similarity index 98% rename from packages/ecs-server/.gitignore rename to modules/ecs/.gitignore index ec337acd..c1eebfc6 100644 --- a/packages/ecs-server/.gitignore +++ b/modules/ecs/.gitignore @@ -267,6 +267,10 @@ dist src/**/*.js src/**/*.d.ts +build/**/*.js +build/**/*.wasm +build/libecs-tmp.d.ts + # pubilc directory lib/ compile_commands.json diff --git a/packages/ecs-server/.prettierignore b/modules/ecs/.prettierignore similarity index 95% rename from packages/ecs-server/.prettierignore rename to modules/ecs/.prettierignore index 711c4e5a..1efdad3f 100644 --- a/packages/ecs-server/.prettierignore +++ b/modules/ecs/.prettierignore @@ -10,4 +10,4 @@ dist/ coverage/ CHANGELOG.md -lib/ +build/ diff --git a/modules/ecs/CHANGELOG.md b/modules/ecs/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/ecs/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/config/LICENSE b/modules/ecs/LICENSE similarity index 97% rename from packages/config/LICENSE rename to modules/ecs/LICENSE index 62c6400b..46724861 100644 --- a/packages/config/LICENSE +++ b/modules/ecs/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/modules/ecs/Makefile b/modules/ecs/Makefile new file mode 100644 index 00000000..b4300867 --- /dev/null +++ b/modules/ecs/Makefile @@ -0,0 +1,61 @@ +SRC = wasm/SparseArray.cpp\ + wasm/Entity.cpp\ + wasm/Utils.cpp\ + wasm/Registry.cpp + +NAME := libecs + +CFLAGS = -std=c++20 +LDFLAGS = -O3 --no-entry --bind -sNO_DISABLE_EXCEPTION_CATCHING -sEXPORT_EXCEPTION_HANDLING_HELPERS + +CC = em++ + +OBJ = $(SRC:.cpp=.o) + +BASE_DIR = build +WEB_DIR = lib/web +NODE_DIR = lib/node + +%.o: %.cpp + $(CC) -c $< -o $@ $(CFLAGS) + +all: base web node + +base: LDFLAGS += -s MODULARIZE=1 +base: $(OBJ) + $(CC) $(OBJ) $(LDFLAGS) --emit-tsd $(NAME)-tmp.d.ts -o $(BASE_DIR)/$(NAME).js + cat $(BASE_DIR)/pre.ts > $(BASE_DIR)/$(NAME).d.ts + cat $(BASE_DIR)/libecs-tmp.d.ts >> $(BASE_DIR)/$(NAME).d.ts + $(RM) $(BASE_DIR)/$(NAME)-tmp.d.ts $(BASE_DIR)/$(NAME).js $(BASE_DIR)/$(NAME).wasm + +web: LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s ENVIRONMENT=web +web: $(OBJ) + @mkdir -p $(WEB_DIR) + $(CC) $(OBJ) $(LDFLAGS) -o $(WEB_DIR)/$(NAME).js + cp $(BASE_DIR)/$(NAME).d.ts $(WEB_DIR)/$(NAME).d.ts + +node: LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 -s ENVIRONMENT=node +node: $(OBJ) + @mkdir -p $(NODE_DIR) + $(CC) $(OBJ) $(LDFLAGS) -o $(NODE_DIR)/$(NAME).js + cp $(BASE_DIR)/$(NAME).d.ts $(NODE_DIR)/$(NAME).d.ts + +tests: LDFLAGS += -s MODULARIZE=1 -s EXPORT_ES6=1 +tests: $(OBJ) + @mkdir -p $(WEB_DIR) $(NODE_DIR) + $(CC) $(OBJ) $(LDFLAGS) -o $(WEB_DIR)/$(NAME).js + cp $(BASE_DIR)/$(NAME).d.ts $(WEB_DIR)/$(NAME).d.ts + sed -i 's/@nanoforge-dev\/common-legacy/@nanoforge-dev\/common/' $(WEB_DIR)/$(NAME).d.ts + cp $(WEB_DIR)/$(NAME).js $(NODE_DIR)/$(NAME).js + cp $(WEB_DIR)/$(NAME).wasm $(NODE_DIR)/$(NAME).wasm + cp $(WEB_DIR)/$(NAME).d.ts $(NODE_DIR)/$(NAME).d.ts + +clean: + $(RM) $(OBJ) + $(RM) -r lib + +fclean: clean + +re: fclean all + +.PHONY: re fclean all clean tests web node diff --git a/modules/ecs/README.md b/modules/ecs/README.md new file mode 100644 index 00000000..d92b47e1 --- /dev/null +++ b/modules/ecs/README.md @@ -0,0 +1,92 @@ +
+
+

+ NanoForge +

+
+

+ npm version + npm downloads + Tests status + Last commit + Contributors +

+
+ +## About + +`@nanoforge-dev/ecs` is NanoForge's built-in entity-component-system library, backed by a WebAssembly registry (compiled from C++). It ships two subpath entry points — `@nanoforge-dev/ecs/client` and `@nanoforge-dev/ecs/server` — each loading its own WASM build (browser-targeted vs Node-targeted) behind the same `EcsLibrary` API, so a client bundle never pulls in the server build or vice versa. + +## Installation + +**Node.js 26 or newer is required.** + +```sh +npm install @nanoforge-dev/ecs +yarn add @nanoforge-dev/ecs +pnpm add @nanoforge-dev/ecs +bun add @nanoforge-dev/ecs +``` + +## Example usage + +Register `EcsLibrary` from the entry point matching your app: + +```ts +// Client app +import { EcsLibrary } from "@nanoforge-dev/ecs/client"; + +app.use(new EcsLibrary()); +``` + +```ts +// Server app +import { EcsLibrary } from "@nanoforge-dev/ecs/server"; + +app.use(new EcsLibrary()); +``` + +Once registered, `Context.ecs.registry` gives every other library access to the entity/component registry: + +```ts +public override async __run(ctx: Context): Promise { + const entity = ctx.ecs.registry.spawnEntity(); + ctx.ecs.registry.addComponent(entity, new Position(0, 0)); +} +``` + +Register systems to run on every tick: + +```ts +ctx.ecs.registry.addSystem((registry) => { + for (const { __RESERVED_entityId, Position } of registry.getZipper([ + { name: "__RESERVED_entityId" }, + { name: "Position" }, + ])) { + // Move things around. + } +}); +``` + +When registered alongside `@nanoforge-dev/editor`'s `EditorLibrary`, `EcsLibrary` also listens for a `"hot-reload"` command from the editor and applies incoming components via `registry.addComponent` — useful for live-editing entity state from an external editor host. + +## Links + +- [GitHub][source] +- [npm][npm] + +## Contributing + +Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the +[documentation][documentation]. +See [the contribution guide][contributing] if you'd like to submit a PR. + +## Help + +If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to ask questions in [discussions][discussions]. + +[documentation]: https://github.com/NanoForge-dev/Engine +[discussions]: https://github.com/NanoForge-dev/Engine/discussions +[source]: https://github.com/NanoForge-dev/Engine/tree/main/modules/ecs +[npm]: https://www.npmjs.com/package/@nanoforge-dev/ecs +[contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/ecs-lib/lib/libecs.d.ts b/modules/ecs/build/libecs.d.ts similarity index 97% rename from packages/ecs-lib/lib/libecs.d.ts rename to modules/ecs/build/libecs.d.ts index 24825128..9fb10755 100644 --- a/packages/ecs-lib/lib/libecs.d.ts +++ b/modules/ecs/build/libecs.d.ts @@ -1,4 +1,4 @@ -import { Context } from "@nanoforge-dev/common"; +import type { Context } from "@nanoforge-dev/common"; export type Component = { name: string; [key: string]: any }; diff --git a/packages/ecs-lib/build/pre.ts b/modules/ecs/build/pre.ts similarity index 70% rename from packages/ecs-lib/build/pre.ts rename to modules/ecs/build/pre.ts index 55a73580..76ce9649 100644 --- a/packages/ecs-lib/build/pre.ts +++ b/modules/ecs/build/pre.ts @@ -1,4 +1,4 @@ -import { Context } from "@nanoforge-dev/common"; +import type { Context } from "@nanoforge-dev/common"; export type Component = { name: string; [key: string]: any }; diff --git a/packages/asset-manager/cliff.toml b/modules/ecs/cliff.toml similarity index 100% rename from packages/asset-manager/cliff.toml rename to modules/ecs/cliff.toml diff --git a/packages/config/eslint.config.js b/modules/ecs/eslint.config.js similarity index 100% rename from packages/config/eslint.config.js rename to modules/ecs/eslint.config.js diff --git a/packages/ecs-server/mint-tsdocs.config.json b/modules/ecs/mint-tsdocs.config.json similarity index 69% rename from packages/ecs-server/mint-tsdocs.config.json rename to modules/ecs/mint-tsdocs.config.json index ee0748a4..3e4e5c30 100644 --- a/packages/ecs-server/mint-tsdocs.config.json +++ b/modules/ecs/mint-tsdocs.config.json @@ -1,7 +1,7 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.ts", - "outputFolder": "../../docs/references/ecs-server", + "entryPoint": "dist/client/index.d.ts", + "outputFolder": "../../docs/references/ecs", "lint": { "eslint": { "enabled": true diff --git a/packages/ecs-client/package.json b/modules/ecs/package.json similarity index 68% rename from packages/ecs-client/package.json rename to modules/ecs/package.json index a4896c9c..dfdd22cc 100644 --- a/packages/ecs-client/package.json +++ b/modules/ecs/package.json @@ -1,8 +1,8 @@ { "$schema": "https://json.schemastore.org/package.json", - "name": "@nanoforge-dev/ecs-client", + "name": "@nanoforge-dev/ecs", "version": "1.4.2", - "description": "NanoForge Engine - ECS Client", + "description": "NanoForge Engine - ECS", "keywords": [ "nanoforge", "game", @@ -13,27 +13,36 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ - "dist", - "lib", - "wasm" + "dist" ], - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.cts", + "main": "./dist/client/index.cjs", + "module": "./dist/client/index.js", + "types": "./dist/client/index.d.cts", "exports": { - ".": { + "./client": { "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" + "types": "./dist/client/index.d.cts", + "default": "./dist/client/index.cjs" }, "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "types": "./dist/client/index.d.ts", + "default": "./dist/client/index.js" + } + }, + "./server": { + "require": { + "types": "./dist/server/index.d.cts", + "default": "./dist/server/index.cjs" + }, + "import": { + "types": "./dist/server/index.d.ts", + "default": "./dist/server/index.js" } }, "./package.json": "./package.json" @@ -45,7 +54,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/ecs-client" + "directory": "modules/ecs" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -57,22 +66,18 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "make fclean && make tests -j 16 && vitest run --config ../../vitest.config.ts && make fclean", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/ecs-client/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/ecs/*'", "release": "cliff-jumper", - "docs": "mint-tsdocs generate" + "docs": "pnpm run build:wasm && mint-tsdocs generate" }, "dependencies": { - "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/ecs-lib": "workspace:*" + "@nanoforge-dev/common": "workspace:*" }, "devDependencies": { "@favware/cliff-jumper": "catalog:ci", - "@nanoforge-dev/asset-manager": "workspace:*", - "@nanoforge-dev/core": "workspace:*", "@nanoforge-dev/utils-eslint-config": "workspace:*", "@nanoforge-dev/utils-prettier-config": "workspace:*", "@trivago/prettier-plugin-sort-imports": "catalog:lint", - "@types/node": "catalog:core", "eslint": "catalog:lint", "prettier": "catalog:lint", "tsdown": "catalog:build", @@ -80,7 +85,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/config/prettier.config.js b/modules/ecs/prettier.config.js similarity index 100% rename from packages/config/prettier.config.js rename to modules/ecs/prettier.config.js diff --git a/modules/ecs/src/client/index.ts b/modules/ecs/src/client/index.ts new file mode 100644 index 00000000..5923f29c --- /dev/null +++ b/modules/ecs/src/client/index.ts @@ -0,0 +1,13 @@ +import { default as Module } from "../../lib/web/libecs"; +import "../shared/context-augmentation"; +import { EcsLibrary as BaseEcsLibrary } from "../shared/ecs-library"; + +/** Client-side ECS library — loads the browser-targeted compiled WASM module. */ +export class EcsLibrary extends BaseEcsLibrary { + constructor() { + super(Module); + } +} + +export type { EcsContextApi } from "../shared/ecs-context.type"; +export type { Component, Entity, Registry, SparseArray, System } from "../../lib/web/libecs"; diff --git a/modules/ecs/src/server/index.ts b/modules/ecs/src/server/index.ts new file mode 100644 index 00000000..74a9f026 --- /dev/null +++ b/modules/ecs/src/server/index.ts @@ -0,0 +1,13 @@ +import { default as Module } from "../../lib/node/libecs"; +import "../shared/context-augmentation"; +import { EcsLibrary as BaseEcsLibrary } from "../shared/ecs-library"; + +/** Server-side ECS library — loads the Node-targeted compiled WASM module. */ +export class EcsLibrary extends BaseEcsLibrary { + constructor() { + super(Module); + } +} + +export type { EcsContextApi } from "../shared/ecs-context.type"; +export type { Component, Entity, Registry, SparseArray, System } from "../../lib/node/libecs"; diff --git a/modules/ecs/src/shared/context-augmentation.ts b/modules/ecs/src/shared/context-augmentation.ts new file mode 100644 index 00000000..34874d3c --- /dev/null +++ b/modules/ecs/src/shared/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { EcsContextApi } from "./ecs-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + ecs: EcsContextApi; + } +} diff --git a/modules/ecs/src/shared/ecs-context.type.ts b/modules/ecs/src/shared/ecs-context.type.ts new file mode 100644 index 00000000..e297e14b --- /dev/null +++ b/modules/ecs/src/shared/ecs-context.type.ts @@ -0,0 +1,7 @@ +import type { Registry } from "../../lib/web/libecs"; + +/** Public surface of `EcsLibrary`, exposed on `Context.ecs`. */ +export interface EcsContextApi { + /** The WASM-backed entity/component registry. */ + readonly registry: Registry; +} diff --git a/modules/ecs/src/shared/ecs-library.ts b/modules/ecs/src/shared/ecs-library.ts new file mode 100644 index 00000000..5746a3a0 --- /dev/null +++ b/modules/ecs/src/shared/ecs-library.ts @@ -0,0 +1,74 @@ +import { + type Context, + type InitContext, + Library, + NfNotFound, + defineLibraryKey, +} from "@nanoforge-dev/common"; + +import type { Entity, MainModule, Registry } from "../../lib/web/libecs"; +import type { EcsContextApi } from "./ecs-context.type"; + +/** Loads the compiled WASM module — supplied by the client/server entry point. */ +export type LoadEcsModule = (options: { locateFile: () => string }) => Promise; + +/** + * ECS library backed by the compiled WASM module. + * + * @remarks + * Loads `libecs.wasm` from `InitContext.files` directly (not `ctx.assets` — + * `Context` doesn't exist yet during `__init`, same phase-boundary + * constraint every library has) and initialises the entity registry. + * + * If registered alongside `@nanoforge-dev/editor-lib`'s `EditorLibrary`, listens + * for a `"hot-reload"` command and applies it via `registry.addComponent`. + * + * Not exported directly — `@nanoforge-dev/ecs/client` and `.../server` each + * subclass this with their own compiled `Module` factory, since the actual + * WASM binary differs by target environment (browser vs Node) even though + * this class's logic is identical either way. + */ +export abstract class EcsLibrary extends Library { + readonly key = defineLibraryKey("ecs"); + + private _module?: MainModule; + private _registry?: Registry; + + protected constructor(private readonly loadModule: LoadEcsModule) { + super({ runAfter: ["graphics"] }); + } + + public override async __init(ctx: InitContext): Promise { + const wasmUrl = ctx.files.get("libecs.wasm"); + if (!wasmUrl) throw new NfNotFound("libecs.wasm", "Asset"); + + this._module = await this.loadModule({ locateFile: () => wasmUrl }); + this._registry = new this._module.Registry(); + + if (ctx.editor) { + ctx.editor.fromEditor.on("hot-reload", (...args: unknown[]) => { + const [entity, component] = args as [Entity, Parameters[1]]; + this.registry.addComponent(entity, component); + }); + } + } + + public override async __run(ctx: Context): Promise { + this.registry.runSystems(ctx); + } + + public get registry(): Registry { + if (!this._registry) this.throwNotInitializedError(); + return this._registry; + } + + public override expose(): EcsContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + get registry() { + return library.registry; + }, + }; + } +} diff --git a/modules/ecs/test/client/ecs-client.spec.ts b/modules/ecs/test/client/ecs-client.spec.ts new file mode 100644 index 00000000..5b52465b --- /dev/null +++ b/modules/ecs/test/client/ecs-client.spec.ts @@ -0,0 +1,148 @@ +import type { Context, InitContext } from "@nanoforge-dev/common"; +import { beforeAll, describe, expect, it, vi } from "vitest"; + +import { EcsLibrary } from "../../src/client"; +import type { Registry } from "../../src/client"; + +class Position { + name = "Position"; + constructor( + public x: number, + public y: number, + ) {} +} + +class Velocity { + name = "Velocity"; + constructor( + public x: number, + public y: number, + ) {} +} + +const makeInitContext = (): InitContext => ({ + vars: { get: () => undefined, set: () => {} }, + env: {}, + files: new Map([["libecs.wasm", "./lib/web/libecs.wasm"]]), +}); + +const makeContext = (): Context => + ({ + app: {} as any, + vars: { get: () => undefined, set: () => {} }, + assets: {} as any, + }) as unknown as Context; + +describe("EcsLibrary (client)", () => { + let ecs: EcsLibrary; + let registry: Registry; + + beforeAll(async () => { + ecs = new EcsLibrary(); + await ecs.__init(makeInitContext()); + registry = ecs.registry; + }); + + describe("metadata", () => { + it("should expose the reserved 'ecs' key", () => { + expect(ecs.key).toBe("ecs"); + }); + }); + + describe("before initialization", () => { + it("should throw when registry is accessed before __init", () => { + expect(() => new EcsLibrary().registry).toThrow(); + }); + }); + + describe("entity management", () => { + it("should spawn entities with incrementing ids", () => { + const e0 = registry.spawnEntity(); + const e1 = registry.spawnEntity(); + expect(e1.getId()).toBe(e0.getId() + 1); + }); + + it("should kill an entity and remove its components", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(1, 2)); + registry.killEntity(entity); + expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); + }); + }); + + describe("component management", () => { + it("should add and override components on an entity", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(1, 2)); + registry.addComponent(entity, new Position(9, 9)); + expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( + new Position(9, 9), + ); + }); + + it("should add multiple component types to the same entity", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(3, 4)); + registry.addComponent(entity, new Velocity(1, 0)); + expect(registry.getComponents(Velocity).get(entity.getId())).toStrictEqual( + new Velocity(1, 0), + ); + }); + + it("should remove a component from an entity", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(1, 2)); + registry.removeComponent(entity, Position); + expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); + }); + }); + + describe("system management", () => { + it("should run all registered systems in order on __run", async () => { + const order: number[] = []; + registry.clearSystems(); + registry.addSystem(() => order.push(1)); + registry.addSystem(() => order.push(2)); + + await ecs.__run(makeContext()); + + expect(order).toStrictEqual([1, 2]); + registry.clearSystems(); + }); + }); + + describe("editor hot-reload", () => { + it("registers a 'hot-reload' listener on ctx.editor once (via __events, not __run), and applies it via addComponent", async () => { + const lib = new EcsLibrary(); + await lib.__init(makeInitContext()); + const reg = lib.registry; + const entity = reg.spawnEntity(); + + const on = vi.fn(); + const ctx = { ...makeContext(), editor: { emit: vi.fn(), on } }; + + await lib.__events(ctx as any); + expect(on).toHaveBeenCalledTimes(1); + expect(on).toHaveBeenCalledWith("hot-reload", expect.any(Function)); + + const handler = on.mock.calls[0]![1] as (...args: unknown[]) => void; + handler(entity, new Position(5, 5)); + expect(reg.getComponents(Position).get(entity.getId())).toStrictEqual(new Position(5, 5)); + + await lib.__events(ctx as any); + expect(on).toHaveBeenCalledTimes(1); // still only wired once + }); + }); + + describe("expose", () => { + it("should expose the same registry via the context API", () => { + expect(ecs.expose().registry).toBe(registry); + }); + }); + + describe("lifecycle", () => { + it("should clear without error", async () => { + await expect(ecs.__clear(makeContext())).resolves.toBeUndefined(); + }); + }); +}); diff --git a/modules/ecs/test/server/ecs-server.spec.ts b/modules/ecs/test/server/ecs-server.spec.ts new file mode 100644 index 00000000..eeefcc07 --- /dev/null +++ b/modules/ecs/test/server/ecs-server.spec.ts @@ -0,0 +1,148 @@ +import type { Context, InitContext } from "@nanoforge-dev/common"; +import { beforeAll, describe, expect, it, vi } from "vitest"; + +import { EcsLibrary } from "../../src/server"; +import type { Registry } from "../../src/server"; + +class Position { + name = "Position"; + constructor( + public x: number, + public y: number, + ) {} +} + +class Velocity { + name = "Velocity"; + constructor( + public x: number, + public y: number, + ) {} +} + +const makeInitContext = (): InitContext => ({ + vars: { get: () => undefined, set: () => {} }, + env: {}, + files: new Map([["libecs.wasm", "./lib/node/libecs.wasm"]]), +}); + +const makeContext = (): Context => + ({ + app: {} as any, + vars: { get: () => undefined, set: () => {} }, + assets: {} as any, + }) as unknown as Context; + +describe("EcsLibrary (server)", () => { + let ecs: EcsLibrary; + let registry: Registry; + + beforeAll(async () => { + ecs = new EcsLibrary(); + await ecs.__init(makeInitContext()); + registry = ecs.registry; + }); + + describe("metadata", () => { + it("should expose the reserved 'ecs' key", () => { + expect(ecs.key).toBe("ecs"); + }); + }); + + describe("before initialization", () => { + it("should throw when registry is accessed before __init", () => { + expect(() => new EcsLibrary().registry).toThrow(); + }); + }); + + describe("entity management", () => { + it("should spawn entities with incrementing ids", () => { + const e0 = registry.spawnEntity(); + const e1 = registry.spawnEntity(); + expect(e1.getId()).toBe(e0.getId() + 1); + }); + + it("should kill an entity and remove its components", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(1, 2)); + registry.killEntity(entity); + expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); + }); + }); + + describe("component management", () => { + it("should add and override components on an entity", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(1, 2)); + registry.addComponent(entity, new Position(9, 9)); + expect(registry.getComponents(Position).get(entity.getId())).toStrictEqual( + new Position(9, 9), + ); + }); + + it("should add multiple component types to the same entity", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(3, 4)); + registry.addComponent(entity, new Velocity(1, 0)); + expect(registry.getComponents(Velocity).get(entity.getId())).toStrictEqual( + new Velocity(1, 0), + ); + }); + + it("should remove a component from an entity", () => { + const entity = registry.spawnEntity(); + registry.addComponent(entity, new Position(1, 2)); + registry.removeComponent(entity, Position); + expect(registry.getComponents(Position).get(entity.getId())).toBeUndefined(); + }); + }); + + describe("system management", () => { + it("should run all registered systems in order on __run", async () => { + const order: number[] = []; + registry.clearSystems(); + registry.addSystem(() => order.push(1)); + registry.addSystem(() => order.push(2)); + + await ecs.__run(makeContext()); + + expect(order).toStrictEqual([1, 2]); + registry.clearSystems(); + }); + }); + + describe("editor hot-reload", () => { + it("registers a 'hot-reload' listener on ctx.editor once (via __events, not __run), and applies it via addComponent", async () => { + const lib = new EcsLibrary(); + await lib.__init(makeInitContext()); + const reg = lib.registry; + const entity = reg.spawnEntity(); + + const on = vi.fn(); + const ctx = { ...makeContext(), editor: { emit: vi.fn(), on } }; + + await lib.__events(ctx as any); + expect(on).toHaveBeenCalledTimes(1); + expect(on).toHaveBeenCalledWith("hot-reload", expect.any(Function)); + + const handler = on.mock.calls[0]![1] as (...args: unknown[]) => void; + handler(entity, new Position(5, 5)); + expect(reg.getComponents(Position).get(entity.getId())).toStrictEqual(new Position(5, 5)); + + await lib.__events(ctx as any); + expect(on).toHaveBeenCalledTimes(1); // still only wired once + }); + }); + + describe("expose", () => { + it("should expose the same registry via the context API", () => { + expect(ecs.expose().registry).toBe(registry); + }); + }); + + describe("lifecycle", () => { + it("should clear without error", async () => { + await expect(ecs.__clear(makeContext())).resolves.toBeUndefined(); + }); + }); +}); diff --git a/packages/asset-manager/tsconfig.json b/modules/ecs/tsconfig.json similarity index 100% rename from packages/asset-manager/tsconfig.json rename to modules/ecs/tsconfig.json diff --git a/packages/asset-manager/tsconfig.spec.json b/modules/ecs/tsconfig.spec.json similarity index 100% rename from packages/asset-manager/tsconfig.spec.json rename to modules/ecs/tsconfig.spec.json diff --git a/packages/asset-manager/tsdoc.json b/modules/ecs/tsdoc.json similarity index 100% rename from packages/asset-manager/tsdoc.json rename to modules/ecs/tsdoc.json diff --git a/modules/ecs/tsdown.config.ts b/modules/ecs/tsdown.config.ts new file mode 100644 index 00000000..cc6d4b65 --- /dev/null +++ b/modules/ecs/tsdown.config.ts @@ -0,0 +1,6 @@ +import { createTsdownConfig } from "../../tsdown.config"; + +export default [ + createTsdownConfig({ entry: "src/client/index.ts", outDir: "dist/client" }), + createTsdownConfig({ entry: "src/server/index.ts", outDir: "dist/server" }), +]; diff --git a/packages/ecs-lib/wasm/Entity.cpp b/modules/ecs/wasm/Entity.cpp similarity index 95% rename from packages/ecs-lib/wasm/Entity.cpp rename to modules/ecs/wasm/Entity.cpp index 30064bb8..fc42f5a5 100644 --- a/packages/ecs-lib/wasm/Entity.cpp +++ b/modules/ecs/wasm/Entity.cpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/Entity.hpp b/modules/ecs/wasm/Entity.hpp similarity index 97% rename from packages/ecs-lib/wasm/Entity.hpp rename to modules/ecs/wasm/Entity.hpp index 27e2f46f..40327742 100644 --- a/packages/ecs-lib/wasm/Entity.hpp +++ b/modules/ecs/wasm/Entity.hpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/Registry.cpp b/modules/ecs/wasm/Registry.cpp similarity index 98% rename from packages/ecs-lib/wasm/Registry.cpp rename to modules/ecs/wasm/Registry.cpp index a20dd52b..68c97d6b 100644 --- a/packages/ecs-lib/wasm/Registry.cpp +++ b/modules/ecs/wasm/Registry.cpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/Registry.hpp b/modules/ecs/wasm/Registry.hpp similarity index 99% rename from packages/ecs-lib/wasm/Registry.hpp rename to modules/ecs/wasm/Registry.hpp index 5912df5a..28fb44cf 100644 --- a/packages/ecs-lib/wasm/Registry.hpp +++ b/modules/ecs/wasm/Registry.hpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/SparseArray.cpp b/modules/ecs/wasm/SparseArray.cpp similarity index 98% rename from packages/ecs-lib/wasm/SparseArray.cpp rename to modules/ecs/wasm/SparseArray.cpp index da9e1f02..ee95ef24 100644 --- a/packages/ecs-lib/wasm/SparseArray.cpp +++ b/modules/ecs/wasm/SparseArray.cpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/SparseArray.hpp b/modules/ecs/wasm/SparseArray.hpp similarity index 99% rename from packages/ecs-lib/wasm/SparseArray.hpp rename to modules/ecs/wasm/SparseArray.hpp index 983507cc..a46f9dba 100644 --- a/packages/ecs-lib/wasm/SparseArray.hpp +++ b/modules/ecs/wasm/SparseArray.hpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/Utils.cpp b/modules/ecs/wasm/Utils.cpp similarity index 97% rename from packages/ecs-lib/wasm/Utils.cpp rename to modules/ecs/wasm/Utils.cpp index ad9ee3ce..494ebd3d 100644 --- a/packages/ecs-lib/wasm/Utils.cpp +++ b/modules/ecs/wasm/Utils.cpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/ecs-lib/wasm/Utils.hpp b/modules/ecs/wasm/Utils.hpp similarity index 96% rename from packages/ecs-lib/wasm/Utils.hpp rename to modules/ecs/wasm/Utils.hpp index e8ae8f74..4b13917d 100644 --- a/packages/ecs-lib/wasm/Utils.hpp +++ b/modules/ecs/wasm/Utils.hpp @@ -7,7 +7,7 @@ ** /_/ |_/\__,_/_/ /_/\____/_/ \____/_/ \__, /\___/ ⠸⣿⡄⠀⠀⠀⠀⣠⣾⣿⣿⣿⣤⠀⠀⠀⠀⢠⣿⠇ ** /____/ ⠀ ⢿⣷⡀⠀⠀⠀⠉⠁⠀⠀⠈⠉⠀⠀⠀⢀⣾⡿⠀ ** ⠀⠀⠹⣿⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⠏⠀⠀ -** 2025 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ +** 2026 ⠀⠀⠀⠈⠙⢿⣷⣶⣤⣤⣤⣤⣶⣾⡿⠋⠁⠀⠀⠀ **⠀ ⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀ */ diff --git a/packages/asset-manager/.idea/.gitignore b/packages/asset-manager/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/asset-manager/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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 deleted file mode 100644 index 01043415..00000000 --- a/packages/asset-manager/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[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 deleted file mode 100644 index 24643cc3..00000000 --- a/packages/asset-manager/.idea/[NanoForge] Engine Asset Manager.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/codeStyles/Project.xml b/packages/asset-manager/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/asset-manager/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml b/packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/asset-manager/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/editor.xml b/packages/asset-manager/.idea/editor.xml deleted file mode 100644 index d9ec4dfd..00000000 --- a/packages/asset-manager/.idea/editor.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - \ 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 deleted file mode 100644 index 7dc12496..00000000 --- a/packages/asset-manager/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ 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 deleted file mode 100644 index 02b915b8..00000000 --- a/packages/asset-manager/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ 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 deleted file mode 100644 index 41ec19c1..00000000 --- a/packages/asset-manager/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/jsLinters/eslint.xml b/packages/asset-manager/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/asset-manager/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/misc.xml b/packages/asset-manager/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/asset-manager/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/modules.xml b/packages/asset-manager/.idea/modules.xml deleted file mode 100644 index b320cde9..00000000 --- a/packages/asset-manager/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/prettier.xml b/packages/asset-manager/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/asset-manager/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/asset-manager/.idea/vcs.xml b/packages/asset-manager/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/asset-manager/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/common/.idea/.gitignore b/packages/common/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/common/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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 deleted file mode 100644 index e68a4537..00000000 --- a/packages/common/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[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 deleted file mode 100644 index 24643cc3..00000000 --- a/packages/common/.idea/[NanoForge] Engine Common.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/common/.idea/codeStyles/Project.xml b/packages/common/.idea/codeStyles/Project.xml deleted file mode 100644 index b70d7533..00000000 --- a/packages/common/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/common/.idea/codeStyles/codeStyleConfig.xml b/packages/common/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/common/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/common/.idea/git_toolbox_blame.xml b/packages/common/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/common/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/common/.idea/git_toolbox_prj.xml b/packages/common/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/common/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/common/.idea/inspectionProfiles/Project_Default.xml b/packages/common/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549e..00000000 --- a/packages/common/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/common/.idea/jsLinters/eslint.xml b/packages/common/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/common/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/common/.idea/modules.xml b/packages/common/.idea/modules.xml deleted file mode 100644 index 78a78280..00000000 --- a/packages/common/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/common/.idea/prettier.xml b/packages/common/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/common/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/common/.idea/vcs.xml b/packages/common/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/common/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/config/.idea/.gitignore b/packages/config/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/config/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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/config/.idea/.name b/packages/config/.idea/.name deleted file mode 100644 index 90621f27..00000000 --- a/packages/config/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine Config \ No newline at end of file diff --git a/packages/config/.idea/[NanoForge] Engine Config.iml b/packages/config/.idea/[NanoForge] Engine Config.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/config/.idea/[NanoForge] Engine Config.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/config/.idea/codeStyles/Project.xml b/packages/config/.idea/codeStyles/Project.xml deleted file mode 100644 index b70d7533..00000000 --- a/packages/config/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/config/.idea/codeStyles/codeStyleConfig.xml b/packages/config/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/config/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/config/.idea/git_toolbox_blame.xml b/packages/config/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/config/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/config/.idea/git_toolbox_prj.xml b/packages/config/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/config/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/config/.idea/inspectionProfiles/Project_Default.xml b/packages/config/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549e..00000000 --- a/packages/config/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/config/.idea/jsLinters/eslint.xml b/packages/config/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/config/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/config/.idea/modules.xml b/packages/config/.idea/modules.xml deleted file mode 100644 index d418d5e0..00000000 --- a/packages/config/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/config/.idea/prettier.xml b/packages/config/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/config/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/config/.idea/vcs.xml b/packages/config/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/config/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/.name b/packages/core-editor/.idea/.name deleted file mode 100644 index b5da13ff..00000000 --- a/packages/core-editor/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine Core Editor \ No newline at end of file diff --git a/packages/core-editor/.idea/[NanoForge] Engine Core Editor.iml b/packages/core-editor/.idea/[NanoForge] Engine Core Editor.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/core-editor/.idea/[NanoForge] Engine Core Editor.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/codeStyles/Project.xml b/packages/core-editor/.idea/codeStyles/Project.xml deleted file mode 100644 index b70d7533..00000000 --- a/packages/core-editor/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/codeStyles/codeStyleConfig.xml b/packages/core-editor/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/core-editor/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/git_toolbox_blame.xml b/packages/core-editor/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/core-editor/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/git_toolbox_prj.xml b/packages/core-editor/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/core-editor/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/inspectionProfiles/Project_Default.xml b/packages/core-editor/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549e..00000000 --- a/packages/core-editor/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/jsLinters/eslint.xml b/packages/core-editor/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/core-editor/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/modules.xml b/packages/core-editor/.idea/modules.xml deleted file mode 100644 index 529602fb..00000000 --- a/packages/core-editor/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/prettier.xml b/packages/core-editor/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/core-editor/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/core-editor/.idea/vcs.xml b/packages/core-editor/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/core-editor/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/core/.idea/.name b/packages/core/.idea/.name deleted file mode 100644 index 3d3e7caa..00000000 --- a/packages/core/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[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 deleted file mode 100644 index 24643cc3..00000000 --- a/packages/core/.idea/[NanoForge] Engine Core.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/core/.idea/codeStyles/Project.xml b/packages/core/.idea/codeStyles/Project.xml deleted file mode 100644 index b70d7533..00000000 --- a/packages/core/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/core/.idea/codeStyles/codeStyleConfig.xml b/packages/core/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/core/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/core/.idea/git_toolbox_blame.xml b/packages/core/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/core/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/core/.idea/git_toolbox_prj.xml b/packages/core/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/core/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/core/.idea/inspectionProfiles/Project_Default.xml b/packages/core/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549e..00000000 --- a/packages/core/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/core/.idea/jsLinters/eslint.xml b/packages/core/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/core/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/core/.idea/modules.xml b/packages/core/.idea/modules.xml deleted file mode 100644 index 99922e22..00000000 --- a/packages/core/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/core/.idea/prettier.xml b/packages/core/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/core/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/core/.idea/vcs.xml b/packages/core/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/core/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/.gitignore b/packages/ecs-client/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/ecs-client/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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-client/.idea/.name b/packages/ecs-client/.idea/.name deleted file mode 100644 index 68cd8cda..00000000 --- a/packages/ecs-client/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine ECS Client \ No newline at end of file diff --git a/packages/ecs-client/.idea/[NanoForge] Engine ECS Client.iml b/packages/ecs-client/.idea/[NanoForge] Engine ECS Client.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/ecs-client/.idea/[NanoForge] Engine ECS Client.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/codeStyles/Project.xml b/packages/ecs-client/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/ecs-client/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/codeStyles/codeStyleConfig.xml b/packages/ecs-client/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/ecs-client/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/editor.xml b/packages/ecs-client/.idea/editor.xml deleted file mode 100644 index d70eddcc..00000000 --- a/packages/ecs-client/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/git_toolbox_blame.xml b/packages/ecs-client/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/ecs-client/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/git_toolbox_prj.xml b/packages/ecs-client/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/ecs-client/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/inspectionProfiles/Project_Default.xml b/packages/ecs-client/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index e852c491..00000000 --- a/packages/ecs-client/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/misc.xml b/packages/ecs-client/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/ecs-client/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/modules.xml b/packages/ecs-client/.idea/modules.xml deleted file mode 100644 index 2ca293ff..00000000 --- a/packages/ecs-client/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/prettier.xml b/packages/ecs-client/.idea/prettier.xml deleted file mode 100644 index b0c1c68f..00000000 --- a/packages/ecs-client/.idea/prettier.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-client/.idea/vcs.xml b/packages/ecs-client/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/ecs-client/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/.gitignore b/packages/ecs-lib/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/ecs-lib/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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-lib/.idea/.name b/packages/ecs-lib/.idea/.name deleted file mode 100644 index 94476ece..00000000 --- a/packages/ecs-lib/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine ECS Lib \ No newline at end of file diff --git a/packages/ecs-lib/.idea/[NanoForge] Engine ECS Lib.iml b/packages/ecs-lib/.idea/[NanoForge] Engine ECS Lib.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/ecs-lib/.idea/[NanoForge] Engine ECS Lib.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/codeStyles/Project.xml b/packages/ecs-lib/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/ecs-lib/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/codeStyles/codeStyleConfig.xml b/packages/ecs-lib/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/ecs-lib/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/editor.xml b/packages/ecs-lib/.idea/editor.xml deleted file mode 100644 index d70eddcc..00000000 --- a/packages/ecs-lib/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/git_toolbox_blame.xml b/packages/ecs-lib/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/ecs-lib/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/git_toolbox_prj.xml b/packages/ecs-lib/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/ecs-lib/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/inspectionProfiles/Project_Default.xml b/packages/ecs-lib/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index e852c491..00000000 --- a/packages/ecs-lib/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/misc.xml b/packages/ecs-lib/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/ecs-lib/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/modules.xml b/packages/ecs-lib/.idea/modules.xml deleted file mode 100644 index 7c8f88d2..00000000 --- a/packages/ecs-lib/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/prettier.xml b/packages/ecs-lib/.idea/prettier.xml deleted file mode 100644 index b0c1c68f..00000000 --- a/packages/ecs-lib/.idea/prettier.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-lib/.idea/vcs.xml b/packages/ecs-lib/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/ecs-lib/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/.gitignore b/packages/ecs-server/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/ecs-server/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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-server/.idea/.name b/packages/ecs-server/.idea/.name deleted file mode 100644 index 4b4c17e7..00000000 --- a/packages/ecs-server/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine ECS Server \ No newline at end of file diff --git a/packages/ecs-server/.idea/[NanoForge] Engine ECS Server.iml b/packages/ecs-server/.idea/[NanoForge] Engine ECS Server.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/ecs-server/.idea/[NanoForge] Engine ECS Server.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/codeStyles/Project.xml b/packages/ecs-server/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/ecs-server/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/codeStyles/codeStyleConfig.xml b/packages/ecs-server/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/ecs-server/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/editor.xml b/packages/ecs-server/.idea/editor.xml deleted file mode 100644 index d70eddcc..00000000 --- a/packages/ecs-server/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/git_toolbox_blame.xml b/packages/ecs-server/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/ecs-server/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/git_toolbox_prj.xml b/packages/ecs-server/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/ecs-server/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/inspectionProfiles/Project_Default.xml b/packages/ecs-server/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index e852c491..00000000 --- a/packages/ecs-server/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/misc.xml b/packages/ecs-server/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/ecs-server/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/modules.xml b/packages/ecs-server/.idea/modules.xml deleted file mode 100644 index 2ad16c09..00000000 --- a/packages/ecs-server/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/prettier.xml b/packages/ecs-server/.idea/prettier.xml deleted file mode 100644 index b0c1c68f..00000000 --- a/packages/ecs-server/.idea/prettier.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/ecs-server/.idea/vcs.xml b/packages/ecs-server/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/ecs-server/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/.gitignore b/packages/graphics-2d-editor/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/graphics-2d-editor/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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-editor/.idea/.name b/packages/graphics-2d-editor/.idea/.name deleted file mode 100644 index 31b37a23..00000000 --- a/packages/graphics-2d-editor/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine Graphics 2D Editor \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/[NanoForge] Engine Graphics 2D Editor.iml b/packages/graphics-2d-editor/.idea/[NanoForge] Engine Graphics 2D Editor.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/graphics-2d-editor/.idea/[NanoForge] Engine Graphics 2D Editor.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/codeStyles/Project.xml b/packages/graphics-2d-editor/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/graphics-2d-editor/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/codeStyles/codeStyleConfig.xml b/packages/graphics-2d-editor/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/graphics-2d-editor/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/editor.xml b/packages/graphics-2d-editor/.idea/editor.xml deleted file mode 100644 index 8c39ae07..00000000 --- a/packages/graphics-2d-editor/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/git_toolbox_blame.xml b/packages/graphics-2d-editor/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/graphics-2d-editor/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/git_toolbox_prj.xml b/packages/graphics-2d-editor/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/graphics-2d-editor/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/inspectionProfiles/Project_Default.xml b/packages/graphics-2d-editor/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 41ec19c1..00000000 --- a/packages/graphics-2d-editor/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/jsLinters/eslint.xml b/packages/graphics-2d-editor/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/graphics-2d-editor/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/misc.xml b/packages/graphics-2d-editor/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/graphics-2d-editor/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/modules.xml b/packages/graphics-2d-editor/.idea/modules.xml deleted file mode 100644 index fa032c30..00000000 --- a/packages/graphics-2d-editor/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/prettier.xml b/packages/graphics-2d-editor/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/graphics-2d-editor/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/graphics-2d-editor/.idea/vcs.xml b/packages/graphics-2d-editor/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/graphics-2d-editor/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/.gitignore b/packages/graphics-2d/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/graphics-2d/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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 deleted file mode 100644 index 81d68e20..00000000 --- a/packages/graphics-2d/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[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 deleted file mode 100644 index 24643cc3..00000000 --- a/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/codeStyles/Project.xml b/packages/graphics-2d/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/graphics-2d/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml b/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/editor.xml b/packages/graphics-2d/.idea/editor.xml deleted file mode 100644 index 8c39ae07..00000000 --- a/packages/graphics-2d/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - \ 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 deleted file mode 100644 index 7dc12496..00000000 --- a/packages/graphics-2d/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ 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 deleted file mode 100644 index 02b915b8..00000000 --- a/packages/graphics-2d/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ 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 deleted file mode 100644 index 41ec19c1..00000000 --- a/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/jsLinters/eslint.xml b/packages/graphics-2d/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/graphics-2d/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/misc.xml b/packages/graphics-2d/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/graphics-2d/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/modules.xml b/packages/graphics-2d/.idea/modules.xml deleted file mode 100644 index 59ac9e2f..00000000 --- a/packages/graphics-2d/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/prettier.xml b/packages/graphics-2d/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/graphics-2d/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/graphics-2d/.idea/vcs.xml b/packages/graphics-2d/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/graphics-2d/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/input/.idea/.gitignore b/packages/input/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/input/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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 deleted file mode 100644 index c81648b1..00000000 --- a/packages/input/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[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 deleted file mode 100644 index 24643cc3..00000000 --- a/packages/input/.idea/[NanoForge] Engine Input.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/input/.idea/codeStyles/Project.xml b/packages/input/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/input/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/input/.idea/codeStyles/codeStyleConfig.xml b/packages/input/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/input/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/input/.idea/editor.xml b/packages/input/.idea/editor.xml deleted file mode 100644 index d9ec4dfd..00000000 --- a/packages/input/.idea/editor.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/input/.idea/git_toolbox_blame.xml b/packages/input/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/input/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/input/.idea/git_toolbox_prj.xml b/packages/input/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/input/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/input/.idea/inspectionProfiles/Project_Default.xml b/packages/input/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 41ec19c1..00000000 --- a/packages/input/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/input/.idea/jsLinters/eslint.xml b/packages/input/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/input/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/input/.idea/misc.xml b/packages/input/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/input/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/input/.idea/modules.xml b/packages/input/.idea/modules.xml deleted file mode 100644 index d1ef2191..00000000 --- a/packages/input/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/input/.idea/prettier.xml b/packages/input/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/input/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/input/.idea/vcs.xml b/packages/input/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/input/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/.gitignore b/packages/network-client/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/network-client/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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/network-client/.idea/.name b/packages/network-client/.idea/.name deleted file mode 100644 index 659d64f8..00000000 --- a/packages/network-client/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine Network Client \ No newline at end of file diff --git a/packages/network-client/.idea/[NanoForge] Engine Network Client.iml b/packages/network-client/.idea/[NanoForge] Engine Network Client.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/network-client/.idea/[NanoForge] Engine Network Client.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/codeStyles/Project.xml b/packages/network-client/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/network-client/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/codeStyles/codeStyleConfig.xml b/packages/network-client/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/network-client/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/editor.xml b/packages/network-client/.idea/editor.xml deleted file mode 100644 index 8c39ae07..00000000 --- a/packages/network-client/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/git_toolbox_blame.xml b/packages/network-client/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/network-client/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/git_toolbox_prj.xml b/packages/network-client/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/network-client/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/inspectionProfiles/Project_Default.xml b/packages/network-client/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 41ec19c1..00000000 --- a/packages/network-client/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/jsLinters/eslint.xml b/packages/network-client/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/network-client/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/misc.xml b/packages/network-client/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/network-client/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/modules.xml b/packages/network-client/.idea/modules.xml deleted file mode 100644 index dd88f163..00000000 --- a/packages/network-client/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/prettier.xml b/packages/network-client/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/network-client/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/network-client/.idea/vcs.xml b/packages/network-client/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/network-client/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/.gitignore b/packages/network-server/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/packages/network-server/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 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/network-server/.idea/.name b/packages/network-server/.idea/.name deleted file mode 100644 index a6e7a493..00000000 --- a/packages/network-server/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -[NanoForge] Engine Network Server \ No newline at end of file diff --git a/packages/network-server/.idea/[NanoForge] Engine Network Server.iml b/packages/network-server/.idea/[NanoForge] Engine Network Server.iml deleted file mode 100644 index 24643cc3..00000000 --- a/packages/network-server/.idea/[NanoForge] Engine Network Server.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/codeStyles/Project.xml b/packages/network-server/.idea/codeStyles/Project.xml deleted file mode 100644 index a57ead77..00000000 --- a/packages/network-server/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/codeStyles/codeStyleConfig.xml b/packages/network-server/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c..00000000 --- a/packages/network-server/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/editor.xml b/packages/network-server/.idea/editor.xml deleted file mode 100644 index 8c39ae07..00000000 --- a/packages/network-server/.idea/editor.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/git_toolbox_blame.xml b/packages/network-server/.idea/git_toolbox_blame.xml deleted file mode 100644 index 7dc12496..00000000 --- a/packages/network-server/.idea/git_toolbox_blame.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/git_toolbox_prj.xml b/packages/network-server/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b8..00000000 --- a/packages/network-server/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/inspectionProfiles/Project_Default.xml b/packages/network-server/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 41ec19c1..00000000 --- a/packages/network-server/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/jsLinters/eslint.xml b/packages/network-server/.idea/jsLinters/eslint.xml deleted file mode 100644 index 541945bb..00000000 --- a/packages/network-server/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/misc.xml b/packages/network-server/.idea/misc.xml deleted file mode 100644 index 7ecbce57..00000000 --- a/packages/network-server/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/modules.xml b/packages/network-server/.idea/modules.xml deleted file mode 100644 index 50edc02c..00000000 --- a/packages/network-server/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/prettier.xml b/packages/network-server/.idea/prettier.xml deleted file mode 100644 index 0c83ac4e..00000000 --- a/packages/network-server/.idea/prettier.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/network-server/.idea/vcs.xml b/packages/network-server/.idea/vcs.xml deleted file mode 100644 index b2bdec2d..00000000 --- a/packages/network-server/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 9f7fbc31a2ff9254f4e074ead46573db1d3f1493 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 17:31:58 +0200 Subject: [PATCH 09/12] feat: add new modules handling (#421) --- .../graphics-2d/.cliff-jumperrc.json | 2 +- .../graphics-2d}/.gitignore | 0 .../graphics-2d}/.prettierignore | 0 modules/graphics-2d/CHANGELOG.md | 3 + .../graphics-2d}/LICENSE | 2 +- {packages => modules}/graphics-2d/README.md | 66 ++---- .../graphics-2d}/cliff.toml | 0 .../graphics-2d}/eslint.config.js | 0 .../graphics-2d/mint-tsdocs.config.json | 0 .../graphics-2d/package.json | 13 +- .../graphics-2d}/prettier.config.js | 0 .../graphics-2d/src/context-augmentation.ts | 7 + .../graphics-2d/src/exports/konva.ts | 0 .../graphics-2d/src/graphics-2d.library.ts | 118 ++++++++++ .../graphics-2d/src/graphics-context.type.ts | 9 + modules/graphics-2d/src/index.ts | 5 + .../test/graphics-2d.library.spec.ts | 132 +++++++++++ .../graphics-2d}/tsconfig.json | 0 .../graphics-2d}/tsconfig.spec.json | 0 .../graphics-2d}/tsdoc.json | 0 .../graphics-2d}/tsdown.config.ts | 0 .../input/.cliff-jumperrc.json | 2 +- .../input}/.gitignore | 0 .../input}/.prettierignore | 0 modules/input/CHANGELOG.md | 3 + .../ecs-client => modules/input}/LICENSE | 2 +- {packages => modules}/input/README.md | 42 ++-- .../ecs-client => modules/input}/cliff.toml | 0 .../input}/eslint.config.js | 0 .../input/mint-tsdocs.config.json | 0 {packages => modules}/input/package.json | 9 +- .../input}/prettier.config.js | 0 modules/input/src/context-augmentation.ts | 7 + modules/input/src/index.ts | 6 + modules/input/src/input-context.type.ts | 13 + modules/input/src/input-handler.ts | 207 ++++++++++++++++ {packages => modules}/input/src/input.enum.ts | 0 modules/input/src/input.library.ts | 102 ++++++++ .../input/src/mouse.types.ts | 0 modules/input/test/input.library.spec.ts | 222 ++++++++++++++++++ .../input}/tsconfig.json | 0 .../input}/tsconfig.spec.json | 0 .../ecs-client => modules/input}/tsdoc.json | 0 .../input}/tsdown.config.ts | 0 .../music/.cliff-jumperrc.json | 2 +- .../music}/.gitignore | 0 .../music}/.prettierignore | 0 modules/music/CHANGELOG.md | 3 + {packages/ecs-lib => modules/music}/LICENSE | 2 +- {packages => modules}/music/README.md | 45 ++-- .../ecs-lib => modules/music}/cliff.toml | 0 .../music}/eslint.config.js | 0 .../music/mint-tsdocs.config.json | 0 {packages => modules}/music/package.json | 9 +- .../music}/prettier.config.js | 0 modules/music/src/context-augmentation.ts | 7 + modules/music/src/index.ts | 4 + modules/music/src/music-context.type.ts | 9 + modules/music/src/music.library.ts | 81 +++++++ .../music/test/music.library.spec.ts | 68 ++++-- .../ecs-lib => modules/music}/tsconfig.json | 0 .../music}/tsconfig.spec.json | 0 .../ecs-lib => modules/music}/tsdoc.json | 0 .../music}/tsdown.config.ts | 0 .../sound/.cliff-jumperrc.json | 2 +- .../graphics-2d => modules/sound}/.gitignore | 36 --- .../music => modules/sound}/.prettierignore | 0 modules/sound/CHANGELOG.md | 3 + .../ecs-server => modules/sound}/LICENSE | 2 +- {packages => modules}/sound/README.md | 43 ++-- .../sound}/cliff.toml | 0 .../input => modules/sound}/eslint.config.js | 0 .../sound/mint-tsdocs.config.json | 0 {packages => modules}/sound/package.json | 9 +- .../sound}/prettier.config.js | 0 modules/sound/src/context-augmentation.ts | 7 + modules/sound/src/index.ts | 4 + modules/sound/src/sound-context.type.ts | 9 + modules/sound/src/sound.library.ts | 72 ++++++ .../sound/test/sound.library.spec.ts | 73 ++++-- .../sound}/tsconfig.json | 0 .../sound}/tsconfig.spec.json | 0 .../sound}/tsdoc.json | 0 .../sound}/tsdown.config.ts | 0 84 files changed, 1219 insertions(+), 243 deletions(-) rename {packages => modules}/graphics-2d/.cliff-jumperrc.json (84%) rename {packages/core-editor => modules/graphics-2d}/.gitignore (100%) rename {packages/core-editor => modules/graphics-2d}/.prettierignore (100%) create mode 100644 modules/graphics-2d/CHANGELOG.md rename {packages/asset-manager => modules/graphics-2d}/LICENSE (97%) rename {packages => modules}/graphics-2d/README.md (56%) rename {packages/core-editor => modules/graphics-2d}/cliff.toml (100%) rename {packages/ecs-client => modules/graphics-2d}/eslint.config.js (100%) rename {packages => modules}/graphics-2d/mint-tsdocs.config.json (100%) rename {packages => modules}/graphics-2d/package.json (86%) rename {packages/ecs-client => modules/graphics-2d}/prettier.config.js (100%) create mode 100644 modules/graphics-2d/src/context-augmentation.ts rename {packages => modules}/graphics-2d/src/exports/konva.ts (100%) create mode 100644 modules/graphics-2d/src/graphics-2d.library.ts create mode 100644 modules/graphics-2d/src/graphics-context.type.ts create mode 100644 modules/graphics-2d/src/index.ts create mode 100644 modules/graphics-2d/test/graphics-2d.library.spec.ts rename {packages/core-editor => modules/graphics-2d}/tsconfig.json (100%) rename {packages/ecs-client => modules/graphics-2d}/tsconfig.spec.json (100%) rename {packages/core-editor => modules/graphics-2d}/tsdoc.json (100%) rename {packages/config => modules/graphics-2d}/tsdown.config.ts (100%) rename {packages => modules}/input/.cliff-jumperrc.json (86%) rename {packages/network-client => modules/input}/.gitignore (100%) rename {packages/graphics-2d-editor => modules/input}/.prettierignore (100%) create mode 100644 modules/input/CHANGELOG.md rename {packages/ecs-client => modules/input}/LICENSE (97%) rename {packages => modules}/input/README.md (66%) rename {packages/ecs-client => modules/input}/cliff.toml (100%) rename {packages/ecs-server => modules/input}/eslint.config.js (100%) rename {packages => modules}/input/mint-tsdocs.config.json (100%) rename {packages => modules}/input/package.json (91%) rename {packages/ecs-lib => modules/input}/prettier.config.js (100%) create mode 100644 modules/input/src/context-augmentation.ts create mode 100644 modules/input/src/index.ts create mode 100644 modules/input/src/input-context.type.ts create mode 100644 modules/input/src/input-handler.ts rename {packages => modules}/input/src/input.enum.ts (100%) create mode 100644 modules/input/src/input.library.ts rename {packages => modules}/input/src/mouse.types.ts (100%) create mode 100644 modules/input/test/input.library.spec.ts rename {packages/ecs-client => modules/input}/tsconfig.json (100%) rename {packages/ecs-lib => modules/input}/tsconfig.spec.json (100%) rename {packages/ecs-client => modules/input}/tsdoc.json (100%) rename {packages/core-editor => modules/input}/tsdown.config.ts (100%) rename {packages => modules}/music/.cliff-jumperrc.json (86%) rename {packages/network-server => modules/music}/.gitignore (100%) rename {packages/graphics-2d => modules/music}/.prettierignore (100%) create mode 100644 modules/music/CHANGELOG.md rename {packages/ecs-lib => modules/music}/LICENSE (97%) rename {packages => modules}/music/README.md (63%) rename {packages/ecs-lib => modules/music}/cliff.toml (100%) rename {packages/graphics-2d-editor => modules/music}/eslint.config.js (100%) rename {packages => modules}/music/mint-tsdocs.config.json (100%) rename {packages => modules}/music/package.json (91%) rename {packages/ecs-server => modules/music}/prettier.config.js (100%) create mode 100644 modules/music/src/context-augmentation.ts create mode 100644 modules/music/src/index.ts create mode 100644 modules/music/src/music-context.type.ts create mode 100644 modules/music/src/music.library.ts rename {packages => modules}/music/test/music.library.spec.ts (63%) rename {packages/ecs-lib => modules/music}/tsconfig.json (100%) rename {packages/ecs-server => modules/music}/tsconfig.spec.json (100%) rename {packages/ecs-lib => modules/music}/tsdoc.json (100%) rename {packages/ecs-client => modules/music}/tsdown.config.ts (100%) rename {packages => modules}/sound/.cliff-jumperrc.json (86%) rename {packages/graphics-2d => modules/sound}/.gitignore (93%) rename {packages/music => modules/sound}/.prettierignore (100%) create mode 100644 modules/sound/CHANGELOG.md rename {packages/ecs-server => modules/sound}/LICENSE (97%) rename {packages => modules}/sound/README.md (64%) rename {packages/graphics-2d-editor => modules/sound}/cliff.toml (100%) rename {packages/input => modules/sound}/eslint.config.js (100%) rename {packages => modules}/sound/mint-tsdocs.config.json (100%) rename {packages => modules}/sound/package.json (91%) rename {packages/graphics-2d => modules/sound}/prettier.config.js (100%) create mode 100644 modules/sound/src/context-augmentation.ts create mode 100644 modules/sound/src/index.ts create mode 100644 modules/sound/src/sound-context.type.ts create mode 100644 modules/sound/src/sound.library.ts rename {packages => modules}/sound/test/sound.library.spec.ts (56%) rename {packages/graphics-2d => modules/sound}/tsconfig.json (100%) rename {packages/graphics-2d => modules/sound}/tsconfig.spec.json (100%) rename {packages/graphics-2d-editor => modules/sound}/tsdoc.json (100%) rename {packages/ecs-lib => modules/sound}/tsdown.config.ts (100%) diff --git a/packages/graphics-2d/.cliff-jumperrc.json b/modules/graphics-2d/.cliff-jumperrc.json similarity index 84% rename from packages/graphics-2d/.cliff-jumperrc.json rename to modules/graphics-2d/.cliff-jumperrc.json index 4460df82..0390faa7 100644 --- a/packages/graphics-2d/.cliff-jumperrc.json +++ b/modules/graphics-2d/.cliff-jumperrc.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", "name": "graphics-2d", "org": "nanoforge-dev", - "packagePath": "packages/graphics-2d", + "packagePath": "modules/graphics-2d", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/core-editor/.gitignore b/modules/graphics-2d/.gitignore similarity index 100% rename from packages/core-editor/.gitignore rename to modules/graphics-2d/.gitignore diff --git a/packages/core-editor/.prettierignore b/modules/graphics-2d/.prettierignore similarity index 100% rename from packages/core-editor/.prettierignore rename to modules/graphics-2d/.prettierignore diff --git a/modules/graphics-2d/CHANGELOG.md b/modules/graphics-2d/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/graphics-2d/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/asset-manager/LICENSE b/modules/graphics-2d/LICENSE similarity index 97% rename from packages/asset-manager/LICENSE rename to modules/graphics-2d/LICENSE index 62c6400b..46724861 100644 --- a/packages/asset-manager/LICENSE +++ b/modules/graphics-2d/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/graphics-2d/README.md b/modules/graphics-2d/README.md similarity index 56% rename from packages/graphics-2d/README.md rename to modules/graphics-2d/README.md index 2781e486..b9761b88 100644 --- a/packages/graphics-2d/README.md +++ b/modules/graphics-2d/README.md @@ -8,18 +8,18 @@ npm version npm downloads Tests status - Last commit + Last commit Contributors

## About -`@nanoforge-dev/graphics-2d` is a base 2D graphics library. +`@nanoforge-dev/graphics-2d` is NanoForge's built-in 2D rendering library, powered by [Konva][konva]. It creates a full-container `Stage` and a default `Layer` and exposes them on `Context.graphics`. Client-only. ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/graphics-2d @@ -30,64 +30,27 @@ bun add @nanoforge-dev/graphics-2d ## Example usage -Initialize the library in your main file with a red circle. +Register `Graphics2DLibrary` on your client app: ```ts -import { type IRunClientOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSClientLibrary } from "@nanoforge-dev/ecs-client"; -import { Circle, Graphics2DLibrary, Layer } from "@nanoforge-dev/graphics-2d"; +import { Graphics2DLibrary } from "@nanoforge-dev/graphics-2d"; -import { CircleComponent } from "./components/CircleComponent"; - -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const ecs = new ECSClientLibrary(); - const graphics = new Graphics2DLibrary(); - - app.useComponentSystem(ecs); - app.useGraphics(graphics); - - await app.init(options); - - const registry = ecs.registry; - - const layer = new Layer(); - graphics.stage.add(layer); - - const entity = registry.spawnEntity(); - registry.addComponent( - entity, - new CircleComponent( - new Circle({ - radius: 70, - fill: "red", - }), - layer, - ), - ); - - await app.run(); -} +app.use(new Graphics2DLibrary()); ``` -With circle component defined. +Draw shapes directly on `Context.graphics.stage`/`.baseLayer`: ```ts -import { type Circle, type Layer } from "@nanoforge-dev/graphics-2d"; +import { Circle } from "@nanoforge-dev/graphics-2d"; -export class CircleComponent { - name = "CircleComponent"; - component: Circle; - - constructor(component: Circle, layer: Layer) { - this.component = component; - layer.add(this.component); - } +public override async __run(ctx: Context): Promise { + const circle = new Circle({ x: 100, y: 100, radius: 40, fill: "red" }); + ctx.graphics.baseLayer.add(circle); } ``` +When registered alongside `@nanoforge-dev/ecs`'s `EcsLibrary` and `@nanoforge-dev/editor`'s `EditorLibrary`, `Graphics2DLibrary` automatically makes any entity carrying a `DrawableCircle2D`/`DrawableRect2D`/`DrawableText2D` component draggable in the viewport and notifies the editor on drag end — no extra wiring required. + ## Links - [GitHub][source] @@ -105,6 +68,7 @@ If you don't understand something in the documentation, you are experiencing pro [documentation]: https://github.com/NanoForge-dev/Engine [discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/graphics-2d +[source]: https://github.com/NanoForge-dev/Engine/tree/main/modules/graphics-2d [npm]: https://www.npmjs.com/package/@nanoforge-dev/graphics-2d [contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md +[konva]: https://konvajs.org/ diff --git a/packages/core-editor/cliff.toml b/modules/graphics-2d/cliff.toml similarity index 100% rename from packages/core-editor/cliff.toml rename to modules/graphics-2d/cliff.toml diff --git a/packages/ecs-client/eslint.config.js b/modules/graphics-2d/eslint.config.js similarity index 100% rename from packages/ecs-client/eslint.config.js rename to modules/graphics-2d/eslint.config.js diff --git a/packages/graphics-2d/mint-tsdocs.config.json b/modules/graphics-2d/mint-tsdocs.config.json similarity index 100% rename from packages/graphics-2d/mint-tsdocs.config.json rename to modules/graphics-2d/mint-tsdocs.config.json diff --git a/packages/graphics-2d/package.json b/modules/graphics-2d/package.json similarity index 86% rename from packages/graphics-2d/package.json rename to modules/graphics-2d/package.json index 2e0af3e6..e95d45fe 100644 --- a/packages/graphics-2d/package.json +++ b/modules/graphics-2d/package.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/package.json", "name": "@nanoforge-dev/graphics-2d", "version": "1.4.2", - "description": "NanoForge Engine - Graphics-2d", + "description": "NanoForge Engine - Graphics 2D", "keywords": [ "nanoforge", "game", @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -43,7 +44,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/graphics-2d" + "directory": "modules/graphics-2d" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -52,7 +53,7 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/graphics-2d/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/graphics-2d/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, @@ -62,6 +63,8 @@ }, "devDependencies": { "@favware/cliff-jumper": "catalog:ci", + "@nanoforge-dev/ecs": "workspace:*", + "@nanoforge-dev/editor-lib": "workspace:*", "@nanoforge-dev/utils-eslint-config": "workspace:*", "@nanoforge-dev/utils-prettier-config": "workspace:*", "@trivago/prettier-plugin-sort-imports": "catalog:lint", @@ -72,7 +75,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/ecs-client/prettier.config.js b/modules/graphics-2d/prettier.config.js similarity index 100% rename from packages/ecs-client/prettier.config.js rename to modules/graphics-2d/prettier.config.js diff --git a/modules/graphics-2d/src/context-augmentation.ts b/modules/graphics-2d/src/context-augmentation.ts new file mode 100644 index 00000000..d8928437 --- /dev/null +++ b/modules/graphics-2d/src/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { GraphicsContextApi } from "./graphics-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + graphics: GraphicsContextApi; + } +} diff --git a/packages/graphics-2d/src/exports/konva.ts b/modules/graphics-2d/src/exports/konva.ts similarity index 100% rename from packages/graphics-2d/src/exports/konva.ts rename to modules/graphics-2d/src/exports/konva.ts diff --git a/modules/graphics-2d/src/graphics-2d.library.ts b/modules/graphics-2d/src/graphics-2d.library.ts new file mode 100644 index 00000000..68fee906 --- /dev/null +++ b/modules/graphics-2d/src/graphics-2d.library.ts @@ -0,0 +1,118 @@ +import { type Context, type InitContext, Library, defineLibraryKey } from "@nanoforge-dev/common"; +// Side-effect-only: loads Context.editor/Context.ecs augmentations for the +// optional editor-drag integration below. graphics-2d is client-only, so +// it only ever coexists with @nanoforge-dev/ecs/client (never /server) in practice. +import type { Registry } from "@nanoforge-dev/ecs/client"; +import type {} from "@nanoforge-dev/editor-lib"; + +import * as Graphics from "./exports/konva"; +import type { GraphicsContextApi } from "./graphics-context.type"; + +type DragSystemEditor = NonNullable; + +/** + * Built-in 2D graphics library powered by [Konva](https://konvajs.org/). + * + * @remarks + * Creates a full-container Konva `Stage` and a default `Layer` during + * `__init`. Game code interacts with `Context.graphics.stage`/`.baseLayer` + * directly to add shapes, images, and animations. Client-only — `__init` + * throws if `InitContext.container` is missing. + */ +export class Graphics2DLibrary extends Library { + readonly key = defineLibraryKey("graphics"); + + private _stage?: Graphics.Stage; + private _baseLayer?: Graphics.Layer; + private _editorDragWired = false; + + public override async __init(ctx: InitContext): Promise { + if (!ctx.container) { + throw new Error( + "Graphics2DLibrary must be registered on the client (InitContext must contain a container element).", + ); + } + this._stage = new Graphics.Stage({ + container: ctx.container, + width: ctx.container.offsetWidth, + height: ctx.container.offsetHeight, + }); + this._baseLayer = new Graphics.Layer(); + this._stage.add(this._baseLayer); + } + + public override async __clear(): Promise { + this._stage?.destroy(); + delete (window as unknown as { Konva?: unknown }).Konva; + } + + /** + * When both an editor bridge and ecs are registered, makes drawable + * shapes (`DrawableCircle2D`/`DrawableRect2D`/`DrawableText2D`) draggable + * in the viewport and notifies the editor on drag end. No-op otherwise — + * plain graphics-2d usage is entirely unaffected. + * + * @remarks + * One-time wiring lives in `__events` (always runs, even while paused), + * not `__run` — so it isn't blocked behind an app that starts paused. + */ + public override async __events(ctx: Context): Promise { + if (!this._editorDragWired && ctx.editor && ctx.ecs) { + ctx.ecs.registry.addSystem(this._dragSystem(ctx.editor)); + this._editorDragWired = true; + } + } + + public get stage(): Graphics.Stage { + if (!this._stage) this.throwNotInitializedError(); + return this._stage; + } + + public get baseLayer(): Graphics.Layer { + if (!this._baseLayer) this.throwNotInitializedError(); + return this._baseLayer; + } + + public override expose(): GraphicsContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + get stage() { + return library.stage; + }, + get baseLayer() { + return library.baseLayer; + }, + }; + } + + private _dragSystem(editor: DragSystemEditor): (registry: Registry) => void { + const wiredComponents = new Map>(); + + return (registry: Registry) => { + const entities = [ + ...registry.getZipper([{ name: "__RESERVED_entityId" }, { name: "DrawableCircle2D" }]), + ...registry.getZipper([{ name: "__RESERVED_entityId" }, { name: "DrawableRect2D" }]), + ...registry.getZipper([{ name: "__RESERVED_entityId" }, { name: "DrawableText2D" }]), + ]; + + for (const entry of entities as any[]) { + const { __RESERVED_entityId, DrawableCircle2D, DrawableRect2D, DrawableText2D } = entry; + const entityId = __RESERVED_entityId.entityId; + + if (!wiredComponents.has(entityId)) wiredComponents.set(entityId, new Set()); + const wired = wiredComponents.get(entityId) as Set; + + for (const comp of [DrawableCircle2D, DrawableRect2D, DrawableText2D]) { + if (!comp || wired.has(comp.name)) continue; + + comp.shape.draggable(true); + comp.shape.on("dragend", ({ target }: any) => { + editor.emit("move-component", entityId, comp.name, target._lastPos); + }); + wired.add(comp.name); + } + } + }; + } +} diff --git a/modules/graphics-2d/src/graphics-context.type.ts b/modules/graphics-2d/src/graphics-context.type.ts new file mode 100644 index 00000000..ba578ba2 --- /dev/null +++ b/modules/graphics-2d/src/graphics-context.type.ts @@ -0,0 +1,9 @@ +import type * as Graphics from "./exports/konva"; + +/** Public surface of `Graphics2DLibrary`, exposed on `Context.graphics`. */ +export interface GraphicsContextApi { + /** The Konva `Stage` covering the client container. */ + readonly stage: Graphics.Stage; + /** The default Konva `Layer` added to the stage — add shapes here to render them. */ + readonly baseLayer: Graphics.Layer; +} diff --git a/modules/graphics-2d/src/index.ts b/modules/graphics-2d/src/index.ts new file mode 100644 index 00000000..16fc5bd1 --- /dev/null +++ b/modules/graphics-2d/src/index.ts @@ -0,0 +1,5 @@ +import "./context-augmentation"; + +export * from "./exports/konva"; +export type { GraphicsContextApi } from "./graphics-context.type"; +export { Graphics2DLibrary } from "./graphics-2d.library"; diff --git a/modules/graphics-2d/test/graphics-2d.library.spec.ts b/modules/graphics-2d/test/graphics-2d.library.spec.ts new file mode 100644 index 00000000..711c527e --- /dev/null +++ b/modules/graphics-2d/test/graphics-2d.library.spec.ts @@ -0,0 +1,132 @@ +import type { InitContext } from "@nanoforge-dev/common"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import { Graphics2DLibrary } from "../src"; + +const makeInitContext = (container: HTMLDivElement | null | undefined): InitContext => + ({ + vars: { get: () => undefined, set: () => {} }, + env: {}, + files: new Map(), + container, + }) as InitContext; + +describe("Graphics2DLibrary", () => { + describe("metadata", () => { + it("should expose the reserved 'graphics' key", () => { + expect(new Graphics2DLibrary().key).toBe("graphics"); + }); + }); + + describe("before initialization", () => { + let library: Graphics2DLibrary; + + beforeEach(() => { + library = new Graphics2DLibrary(); + }); + + it("should throw when stage is accessed before __init", () => { + expect(() => library.stage).toThrow(); + }); + + it("should throw when baseLayer is accessed before __init", () => { + expect(() => library.baseLayer).toThrow(); + }); + + it("should throw when __init is called without a container", async () => { + await expect(library.__init(makeInitContext(null))).rejects.toThrow(); + await expect(library.__init(makeInitContext(undefined))).rejects.toThrow(); + }); + }); + + describe("__clear", () => { + beforeEach(() => { + vi.stubGlobal("window", {}); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it("does not throw when called before __init", async () => { + await expect(new Graphics2DLibrary().__clear({} as any)).resolves.toBeUndefined(); + }); + }); + + describe("expose", () => { + it("throws through to the same not-initialized guard as the instance getters", () => { + const library = new Graphics2DLibrary(); + expect(() => library.expose().stage).toThrow(); + expect(() => library.expose().baseLayer).toThrow(); + }); + }); + + describe("editor drag integration", () => { + const makeShape = () => ({ + draggable: vi.fn(), + on: vi.fn(), + }); + + const makeEntry = (entityId: string, shapes: Record>) => ({ + __RESERVED_entityId: { entityId }, + ...Object.fromEntries(Object.entries(shapes).map(([name, shape]) => [name, { name, shape }])), + }); + + it("does nothing when ctx.editor or ctx.ecs is absent", async () => { + const library = new Graphics2DLibrary(); + await expect( + library.__events({ editor: undefined, ecs: undefined } as any), + ).resolves.toBeUndefined(); + }); + + it("makes drawable shapes draggable and emits move-component on drag end, once per component", async () => { + const library = new Graphics2DLibrary(); + const shape = makeShape(); + const entries = [makeEntry("entity-1", { DrawableCircle2D: shape })]; + const getZipper = vi.fn((components: { name: string }[]) => + components.some((c) => c.name === "DrawableCircle2D") ? entries : [], + ); + const addSystem = vi.fn(); + const emit = vi.fn(); + + const ctx = { + editor: { emit, on: vi.fn() }, + ecs: { registry: { getZipper, addSystem } }, + } as any; + + await library.__events(ctx); + expect(addSystem).toHaveBeenCalledOnce(); + + const system = addSystem.mock.calls[0]![0] as (registry: unknown) => void; + system({ getZipper }); + expect(shape.draggable).toHaveBeenCalledWith(true); + expect(shape.on).toHaveBeenCalledWith("dragend", expect.any(Function)); + + const dragEndHandler = shape.on.mock.calls[0]![1] as (e: any) => void; + dragEndHandler({ target: { _lastPos: { x: 1, y: 2 } } }); + expect(emit).toHaveBeenCalledWith("move-component", "entity-1", "DrawableCircle2D", { + x: 1, + y: 2, + }); + + // Running the system again for the same entity/component must not re-wire it. + system({ getZipper }); + expect(shape.draggable).toHaveBeenCalledOnce(); + expect(shape.on).toHaveBeenCalledOnce(); + }); + + it("only wires the drag system once across multiple __events calls", async () => { + const library = new Graphics2DLibrary(); + const addSystem = vi.fn(); + const ctx = { + editor: { emit: vi.fn(), on: vi.fn() }, + ecs: { registry: { getZipper: vi.fn(() => []), addSystem } }, + } as any; + + await library.__events(ctx); + await library.__events(ctx); + + expect(addSystem).toHaveBeenCalledOnce(); + }); + }); +}); diff --git a/packages/core-editor/tsconfig.json b/modules/graphics-2d/tsconfig.json similarity index 100% rename from packages/core-editor/tsconfig.json rename to modules/graphics-2d/tsconfig.json diff --git a/packages/ecs-client/tsconfig.spec.json b/modules/graphics-2d/tsconfig.spec.json similarity index 100% rename from packages/ecs-client/tsconfig.spec.json rename to modules/graphics-2d/tsconfig.spec.json diff --git a/packages/core-editor/tsdoc.json b/modules/graphics-2d/tsdoc.json similarity index 100% rename from packages/core-editor/tsdoc.json rename to modules/graphics-2d/tsdoc.json diff --git a/packages/config/tsdown.config.ts b/modules/graphics-2d/tsdown.config.ts similarity index 100% rename from packages/config/tsdown.config.ts rename to modules/graphics-2d/tsdown.config.ts diff --git a/packages/input/.cliff-jumperrc.json b/modules/input/.cliff-jumperrc.json similarity index 86% rename from packages/input/.cliff-jumperrc.json rename to modules/input/.cliff-jumperrc.json index e77a22e6..c92fa0a1 100644 --- a/packages/input/.cliff-jumperrc.json +++ b/modules/input/.cliff-jumperrc.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", "name": "input", "org": "nanoforge-dev", - "packagePath": "packages/input", + "packagePath": "modules/input", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/network-client/.gitignore b/modules/input/.gitignore similarity index 100% rename from packages/network-client/.gitignore rename to modules/input/.gitignore diff --git a/packages/graphics-2d-editor/.prettierignore b/modules/input/.prettierignore similarity index 100% rename from packages/graphics-2d-editor/.prettierignore rename to modules/input/.prettierignore diff --git a/modules/input/CHANGELOG.md b/modules/input/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/input/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/ecs-client/LICENSE b/modules/input/LICENSE similarity index 97% rename from packages/ecs-client/LICENSE rename to modules/input/LICENSE index 62c6400b..46724861 100644 --- a/packages/ecs-client/LICENSE +++ b/modules/input/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/input/README.md b/modules/input/README.md similarity index 66% rename from packages/input/README.md rename to modules/input/README.md index 8b0d0b41..e6ac6b5b 100644 --- a/packages/input/README.md +++ b/modules/input/README.md @@ -8,18 +8,18 @@ npm version npm downloads Tests status - Last commit + Last commit Contributors

## About -`@nanoforge-dev/input` is an input manager for handling keyboard and mouse events. +`@nanoforge-dev/input` is NanoForge's built-in keyboard/mouse input library. It listens to browser keyboard and mouse events and exposes a per-frame snapshot of the current input state on `Context.input`. Client-only. ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/input @@ -30,38 +30,34 @@ bun add @nanoforge-dev/input ## Example usage -Initialize the library in your main file +Register `InputLibrary` on your client app: ```ts -import { type IRunClientOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; import { InputLibrary } from "@nanoforge-dev/input"; -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const input = new InputLibrary(); - - app.useInput(input); - - await app.init(options); - - await app.run(); -} +app.use(new InputLibrary()); ``` -Use to check for key presses +Query the current input state from any library's `__run`: ```ts -export function mySystem(registry: Registry, ctx: Context) { - const input = ctx.libs.getInput(); +import { InputEnum } from "@nanoforge-dev/input"; + +public override async __run(ctx: Context): Promise { + if (ctx.input.isKeyPressed(InputEnum.Space)) { + player.jump(); + } - const isArrowUpPressed = input.isKeyPressed(InputEnum.ArrowUp); + if (ctx.input.isDragging(InputEnum.MouseLeft)) { + camera.pan(ctx.input.getDragState()); + } - // Do something with the input + const { x, y } = ctx.input.getMousePosition(); } ``` +`Context.input` also exposes `getPressedKeys()`, `getMouseState()`, and `getWheelState()` for scroll input. + ## Links - [GitHub][source] @@ -79,6 +75,6 @@ If you don't understand something in the documentation, you are experiencing pro [documentation]: https://github.com/NanoForge-dev/Engine [discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/input +[source]: https://github.com/NanoForge-dev/Engine/tree/main/modules/input [npm]: https://www.npmjs.com/package/@nanoforge-dev/input [contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/ecs-client/cliff.toml b/modules/input/cliff.toml similarity index 100% rename from packages/ecs-client/cliff.toml rename to modules/input/cliff.toml diff --git a/packages/ecs-server/eslint.config.js b/modules/input/eslint.config.js similarity index 100% rename from packages/ecs-server/eslint.config.js rename to modules/input/eslint.config.js diff --git a/packages/input/mint-tsdocs.config.json b/modules/input/mint-tsdocs.config.json similarity index 100% rename from packages/input/mint-tsdocs.config.json rename to modules/input/mint-tsdocs.config.json diff --git a/packages/input/package.json b/modules/input/package.json similarity index 91% rename from packages/input/package.json rename to modules/input/package.json index 536dd170..cb3657a0 100644 --- a/packages/input/package.json +++ b/modules/input/package.json @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -43,7 +44,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/input" + "directory": "modules/input" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -52,7 +53,7 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/input/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/input/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, @@ -71,7 +72,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/ecs-lib/prettier.config.js b/modules/input/prettier.config.js similarity index 100% rename from packages/ecs-lib/prettier.config.js rename to modules/input/prettier.config.js diff --git a/modules/input/src/context-augmentation.ts b/modules/input/src/context-augmentation.ts new file mode 100644 index 00000000..b0044ce1 --- /dev/null +++ b/modules/input/src/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { InputContextApi } from "./input-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + input: InputContextApi; + } +} diff --git a/modules/input/src/index.ts b/modules/input/src/index.ts new file mode 100644 index 00000000..c3ea2db1 --- /dev/null +++ b/modules/input/src/index.ts @@ -0,0 +1,6 @@ +import "./context-augmentation"; + +export { InputEnum } from "./input.enum"; +export type { InputContextApi } from "./input-context.type"; +export { InputLibrary } from "./input.library"; +export type { DragState, MouseState, WheelState } from "./mouse.types"; diff --git a/modules/input/src/input-context.type.ts b/modules/input/src/input-context.type.ts new file mode 100644 index 00000000..c1b6f499 --- /dev/null +++ b/modules/input/src/input-context.type.ts @@ -0,0 +1,13 @@ +import type { InputEnum } from "./input.enum"; +import type { DragState, MouseState, WheelState } from "./mouse.types"; + +/** Public surface of `InputLibrary`, exposed on `Context.input`. */ +export interface InputContextApi { + isKeyPressed(key: InputEnum): boolean | undefined; + getPressedKeys(): InputEnum[]; + getMousePosition(): { x: number; y: number }; + getMouseState(): MouseState; + isDragging(button?: InputEnum): boolean; + getDragState(): DragState; + getWheelState(): WheelState; +} diff --git a/modules/input/src/input-handler.ts b/modules/input/src/input-handler.ts new file mode 100644 index 00000000..edc4ed40 --- /dev/null +++ b/modules/input/src/input-handler.ts @@ -0,0 +1,207 @@ +import { InputEnum } from "./input.enum"; +import { + BUTTONS_MASKS, + type DragState, + MOUSE_BUTTON_MAP, + type MouseState, + type WheelState, +} from "./mouse.types"; + +export class InputHandler { + private readonly offset: { x: number; y: number }; + private readonly container: HTMLDivElement; + public inputs: Record = {}; + public mouse: MouseState = { + x: 0, + y: 0, + prevX: 0, + prevY: 0, + deltaX: 0, + deltaY: 0, + focus: false, + }; + public wheel: WheelState = { + deltaX: 0, + deltaY: 0, + deltaZ: 0, + }; + public drag: DragState = { + active: false, + startX: 0, + startY: 0, + x: 0, + y: 0, + deltaX: 0, + deltaY: 0, + }; + + constructor(container: HTMLDivElement) { + this.container = container; + this.resetInputs(); + + this.offset = container.getBoundingClientRect(); + + window.addEventListener("keydown", this.onKeyDown); + window.addEventListener("keyup", this.onKeyUp); + container.addEventListener("mousedown", this.onMouseDown); + container.addEventListener("mouseup", this.onMouseUp); + container.addEventListener("mousemove", this.onMouseMove); + container.addEventListener("wheel", this.onWheel); + container.addEventListener("mouseenter", this.onMouseEnter); + container.addEventListener("mouseleave", this.onMouseLeave); + container.addEventListener("blur", this.onBlur); + container.addEventListener("visibilitychange", this.onVisibilityChange); + + for (const key in InputEnum) { + this.inputs[key] = false; + } + } + + /** Removes every listener registered by the constructor. */ + public destroy(): void { + window.removeEventListener("keydown", this.onKeyDown); + window.removeEventListener("keyup", this.onKeyUp); + this.container.removeEventListener("mousedown", this.onMouseDown); + this.container.removeEventListener("mouseup", this.onMouseUp); + this.container.removeEventListener("mousemove", this.onMouseMove); + this.container.removeEventListener("wheel", this.onWheel); + this.container.removeEventListener("mouseenter", this.onMouseEnter); + this.container.removeEventListener("mouseleave", this.onMouseLeave); + this.container.removeEventListener("blur", this.onBlur); + this.container.removeEventListener("visibilitychange", this.onVisibilityChange); + } + + public getKeyStatus(key: InputEnum): boolean { + return this.inputs[key] || false; + } + + public getMousePosition(): { x: number; y: number } { + return { x: this.mouse.x, y: this.mouse.y }; + } + + public isDragging(button?: InputEnum): boolean { + if (!button) return this.drag.active; + return this.drag.active && this.drag.button === button; + } + + public resetPerFrame(): void { + this.mouse.deltaX = 0; + this.mouse.deltaY = 0; + this.wheel.deltaX = 0; + this.wheel.deltaY = 0; + this.wheel.deltaZ = 0; + } + + private readonly onKeyDown = (e: KeyboardEvent): void => { + this.inputs[e.code] = true; + }; + + private readonly onKeyUp = (e: KeyboardEvent): void => { + this.inputs[e.code] = false; + }; + + private readonly onMouseDown = (e: MouseEvent): void => { + const button = MOUSE_BUTTON_MAP[e.button]; + if (button === undefined) return; + + this.inputs[button] = true; + this.updatePointer(e); + + this.drag.active = true; + this.drag.button = button; + this.drag.startX = e.clientX - this.offset.x; + this.drag.startY = e.clientY - this.offset.y; + this.drag.x = e.clientX - this.offset.x; + this.drag.y = e.clientY - this.offset.y; + this.drag.deltaX = 0; + this.drag.deltaY = 0; + }; + + private readonly onMouseUp = (e: MouseEvent): void => { + const button = MOUSE_BUTTON_MAP[e.button]; + if (button !== undefined) this.inputs[button] = false; + + this.updatePointer(e); + + if (this.drag.button === button) { + this.drag.active = false; + this.drag.button = undefined; + this.drag.x = 0; + this.drag.y = 0; + this.drag.deltaX = 0; + this.drag.deltaY = 0; + } + }; + + private readonly onMouseMove = (e: MouseEvent): void => { + this.updatePointer(e); + this.updateInputsMouseButtons(e.buttons); + + if (this.drag.active) { + this.drag.x = e.clientX - this.offset.x; + this.drag.y = e.clientY - this.offset.y; + this.drag.deltaX = e.clientX - this.drag.startX - this.offset.x; + this.drag.deltaY = e.clientY - this.drag.startY - this.offset.y; + } + }; + + private readonly onWheel = (e: WheelEvent): void => { + this.wheel.deltaX += e.deltaX; + this.wheel.deltaY += e.deltaY; + this.wheel.deltaZ += e.deltaZ; + }; + + private readonly onMouseEnter = (): void => { + this.mouse.focus = true; + }; + + private readonly onMouseLeave = (): void => { + this.mouse.focus = false; + }; + + private readonly onBlur = (): void => { + this.resetInputs(); + }; + + private readonly onVisibilityChange = (): void => { + if (document.hidden) this.resetInputs(); + }; + + private updatePointer(e: MouseEvent): void { + this.mouse.prevX = this.mouse.x; + this.mouse.prevY = this.mouse.y; + this.mouse.x = e.clientX - this.offset.x; + this.mouse.y = e.clientY - this.offset.y; + this.mouse.deltaX = this.mouse.x - this.mouse.prevX; + this.mouse.deltaY = this.mouse.y - this.mouse.prevY; + } + + private updateInputsMouseButtons(buttons: number): void { + for (const [mask, input] of BUTTONS_MASKS) { + this.inputs[input] = (buttons & mask) !== 0; + } + } + + private resetInputs(): void { + for (const key of Object.values(InputEnum)) { + this.inputs[key] = false; + } + + this.drag.active = false; + this.drag.button = undefined; + this.drag.startX = 0; + this.drag.startY = 0; + this.drag.x = 0; + this.drag.y = 0; + this.drag.deltaX = 0; + this.drag.deltaY = 0; + + this.wheel.deltaX = 0; + this.wheel.deltaY = 0; + this.wheel.deltaZ = 0; + + this.mouse.deltaX = 0; + this.mouse.deltaY = 0; + this.mouse.focus = false; + } +} diff --git a/packages/input/src/input.enum.ts b/modules/input/src/input.enum.ts similarity index 100% rename from packages/input/src/input.enum.ts rename to modules/input/src/input.enum.ts diff --git a/modules/input/src/input.library.ts b/modules/input/src/input.library.ts new file mode 100644 index 00000000..423cb62c --- /dev/null +++ b/modules/input/src/input.library.ts @@ -0,0 +1,102 @@ +import { type InitContext, Library, defineLibraryKey } from "@nanoforge-dev/common"; + +import type { InputContextApi } from "./input-context.type"; +import { InputHandler } from "./input-handler"; +import type { InputEnum } from "./input.enum"; +import type { DragState, MouseState, WheelState } from "./mouse.types"; + +/** + * Built-in input library. + * + * @remarks + * Listens to browser `keydown`/`keyup` (on `window`) and `mousedown`/ + * `mouseup`/`mousemove`/`wheel`/`mouseenter`/`mouseleave`/`blur`/ + * `visibilitychange` (on the client container) and exposes a per-frame + * snapshot of the current input state on `Context.input`. Client-only — + * `__init` throws if `InitContext.container` is missing. + */ +export class InputLibrary extends Library { + readonly key = defineLibraryKey("input"); + + private _inputHandler?: InputHandler; + + constructor() { + super({ runAfter: ["graphics"] }); + } + + public override async __init(ctx: InitContext): Promise { + if (!ctx.container) { + throw new Error( + "InputLibrary must be registered on the client (InitContext must contain a container element).", + ); + } + this._inputHandler = new InputHandler(ctx.container); + } + + public override async __run(): Promise { + if (!this._inputHandler) this.throwNotInitializedError(); + this._inputHandler.resetPerFrame(); + } + + public override async __clear(): Promise { + this._inputHandler?.destroy(); + } + + /** + * @returns `true`/`false` for a held/released key, `undefined` if the key + * has never been seen. + */ + public isKeyPressed(key: InputEnum): boolean | undefined { + if (!this._inputHandler) this.throwNotInitializedError(); + return this._inputHandler.getKeyStatus(key); + } + + public getPressedKeys(): InputEnum[] { + if (!this._inputHandler) this.throwNotInitializedError(); + const pressed: InputEnum[] = []; + for (const rawKey in this._inputHandler.inputs) { + const key = rawKey as InputEnum; + if (this._inputHandler.getKeyStatus(key)) pressed.push(key); + } + return pressed; + } + + public getMousePosition(): { x: number; y: number } { + if (!this._inputHandler) this.throwNotInitializedError(); + return this._inputHandler.getMousePosition(); + } + + public getMouseState(): MouseState { + if (!this._inputHandler) this.throwNotInitializedError(); + return this._inputHandler.mouse; + } + + public isDragging(button?: InputEnum): boolean { + if (!this._inputHandler) this.throwNotInitializedError(); + return this._inputHandler.isDragging(button); + } + + public getDragState(): DragState { + if (!this._inputHandler) this.throwNotInitializedError(); + return this._inputHandler.drag; + } + + public getWheelState(): WheelState { + if (!this._inputHandler) this.throwNotInitializedError(); + return this._inputHandler.wheel; + } + + public override expose(): InputContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + isKeyPressed: (key) => library.isKeyPressed(key), + getPressedKeys: () => library.getPressedKeys(), + getMousePosition: () => library.getMousePosition(), + getMouseState: () => library.getMouseState(), + isDragging: (button) => library.isDragging(button), + getDragState: () => library.getDragState(), + getWheelState: () => library.getWheelState(), + }; + } +} diff --git a/packages/input/src/mouse.types.ts b/modules/input/src/mouse.types.ts similarity index 100% rename from packages/input/src/mouse.types.ts rename to modules/input/src/mouse.types.ts diff --git a/modules/input/test/input.library.spec.ts b/modules/input/test/input.library.spec.ts new file mode 100644 index 00000000..558b810c --- /dev/null +++ b/modules/input/test/input.library.spec.ts @@ -0,0 +1,222 @@ +import type { InitContext } from "@nanoforge-dev/common"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import { InputEnum, InputLibrary } from "../src"; + +type MockInputEvent = { + code?: string; + button?: number; + buttons?: number; + clientX?: number; + clientY?: number; + deltaX?: number; + deltaY?: number; + deltaZ?: number; +}; + +const makeEventTargetMock = () => { + const listeners: Record void)[]> = {}; + return { + addEventListener: vi.fn((event: string, handler: (e: MockInputEvent) => void) => { + if (!listeners[event]) listeners[event] = []; + listeners[event].push(handler); + }), + removeEventListener: vi.fn((event: string, handler: (e: MockInputEvent) => void) => { + listeners[event] = (listeners[event] ?? []).filter((h) => h !== handler); + }), + dispatch: (event: string, e: Partial) => { + listeners[event]?.forEach((h) => h(e as MockInputEvent)); + }, + }; +}; + +const makeInitContext = (container: unknown): InitContext => + ({ + vars: { get: () => undefined, set: () => {} }, + env: {}, + files: new Map(), + container, + }) as InitContext; + +describe("InputLibrary", () => { + let windowMock: ReturnType & { + getBoundingClientRect: () => { x: number; y: number }; + }; + let documentMock: ReturnType & { hidden: boolean }; + + beforeEach(() => { + windowMock = { ...makeEventTargetMock(), getBoundingClientRect: () => ({ x: 0, y: 0 }) }; + documentMock = { ...makeEventTargetMock(), hidden: false }; + + vi.stubGlobal("window", windowMock); + vi.stubGlobal("document", documentMock); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + describe("metadata", () => { + it("should expose the reserved 'input' key", () => { + expect(new InputLibrary().key).toBe("input"); + }); + }); + + describe("before initialization", () => { + it("should throw when methods are called before __init", () => { + const library = new InputLibrary(); + expect(() => library.isKeyPressed(InputEnum.KeyA)).toThrow(); + expect(() => library.getPressedKeys()).toThrow(); + expect(() => library.getMousePosition()).toThrow(); + expect(() => library.getMouseState()).toThrow(); + expect(() => library.isDragging()).toThrow(); + expect(() => library.getDragState()).toThrow(); + expect(() => library.getWheelState()).toThrow(); + }); + + it("should throw when __init is called without a container", async () => { + const library = new InputLibrary(); + await expect(library.__init(makeInitContext(undefined))).rejects.toThrow(); + }); + + it("should throw when __run is called before __init", async () => { + const library = new InputLibrary(); + await expect(library.__run({} as any)).rejects.toThrow(); + }); + }); + + describe("after initialization", () => { + let library: InputLibrary; + + beforeEach(async () => { + library = new InputLibrary(); + await library.__init(makeInitContext(windowMock)); + }); + + it("should register all expected event listeners", () => { + for (const event of [ + "keydown", + "keyup", + "mousedown", + "mouseup", + "mousemove", + "wheel", + "mouseenter", + "mouseleave", + "blur", + "visibilitychange", + ]) { + expect(windowMock.addEventListener).toHaveBeenCalledWith(event, expect.any(Function)); + } + }); + + it("should return false for any key before any key event", () => { + expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); + }); + + it("should return true for a key after keydown, then false after keyup", () => { + windowMock.dispatch("keydown", { code: InputEnum.KeyA }); + expect(library.isKeyPressed(InputEnum.KeyA)).toBe(true); + + windowMock.dispatch("keyup", { code: InputEnum.KeyA }); + expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); + }); + + it("should list currently pressed keys", () => { + windowMock.dispatch("keydown", { code: InputEnum.KeyA }); + windowMock.dispatch("keydown", { code: InputEnum.Space }); + const pressed = library.getPressedKeys(); + expect(pressed).toContain(InputEnum.KeyA); + expect(pressed).toContain(InputEnum.Space); + expect(pressed).toHaveLength(2); + }); + + it("should handle mouse button press and release", () => { + windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); + expect(library.isKeyPressed(InputEnum.MouseLeft)).toBe(true); + + windowMock.dispatch("mouseup", { button: 0, clientX: 10, clientY: 20 }); + expect(library.isKeyPressed(InputEnum.MouseLeft)).toBe(false); + }); + + it("should update mouse position and delta on move", () => { + windowMock.dispatch("mousemove", { clientX: 100, clientY: 200, buttons: 0 }); + + expect(library.getMousePosition()).toStrictEqual({ x: 100, y: 200 }); + expect(library.getMouseState()).toMatchObject({ x: 100, y: 200, deltaX: 100, deltaY: 200 }); + }); + + it("should start, update and stop dragging", () => { + windowMock.dispatch("mousedown", { button: 0, clientX: 10, clientY: 20 }); + expect(library.isDragging(InputEnum.MouseLeft)).toBe(true); + + windowMock.dispatch("mousemove", { clientX: 25, clientY: 45, buttons: 1 }); + expect(library.getDragState()).toMatchObject({ x: 25, y: 45, deltaX: 15, deltaY: 25 }); + + windowMock.dispatch("mouseup", { button: 0, clientX: 25, clientY: 45 }); + expect(library.isDragging()).toBe(false); + }); + + it("should accumulate wheel delta and reset it on __run", async () => { + windowMock.dispatch("wheel", { deltaX: 1, deltaY: 2, deltaZ: 3 }); + windowMock.dispatch("wheel", { deltaX: 4, deltaY: 5, deltaZ: 6 }); + expect(library.getWheelState()).toStrictEqual({ deltaX: 5, deltaY: 7, deltaZ: 9 }); + + await library.__run({} as any); + + expect(library.getWheelState()).toStrictEqual({ deltaX: 0, deltaY: 0, deltaZ: 0 }); + }); + + it("should reset inputs on blur", () => { + windowMock.dispatch("keydown", { code: InputEnum.KeyA }); + windowMock.dispatch("blur", {}); + expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); + }); + + it("should reset inputs when document becomes hidden", () => { + windowMock.dispatch("keydown", { code: InputEnum.KeyA }); + documentMock.hidden = true; + windowMock.dispatch("visibilitychange", {}); + expect(library.isKeyPressed(InputEnum.KeyA)).toBe(false); + }); + + it("should update pointer focus on mouse enter and leave", () => { + windowMock.dispatch("mouseenter", {}); + expect(library.getMouseState().focus).toBe(true); + + windowMock.dispatch("mouseleave", {}); + expect(library.getMouseState().focus).toBe(false); + }); + }); + + describe("__clear", () => { + it("removes every registered listener", async () => { + const library = new InputLibrary(); + await library.__init(makeInitContext(windowMock)); + + await library.__clear({} as any); + + expect(windowMock.removeEventListener).toHaveBeenCalledWith("keydown", expect.any(Function)); + expect(windowMock.removeEventListener).toHaveBeenCalledWith("keyup", expect.any(Function)); + expect(windowMock.removeEventListener).toHaveBeenCalledWith( + "mousedown", + expect.any(Function), + ); + expect(windowMock.removeEventListener.mock.calls.length).toBeGreaterThanOrEqual(10); + }); + + it("does not throw when called before __init", async () => { + await expect(new InputLibrary().__clear({} as any)).resolves.toBeUndefined(); + }); + }); + + describe("expose", () => { + it("returns bound methods that behave like the instance methods", async () => { + const library = new InputLibrary(); + await library.__init(makeInitContext(windowMock)); + windowMock.dispatch("keydown", { code: InputEnum.KeyA }); + + expect(library.expose().isKeyPressed(InputEnum.KeyA)).toBe(true); + }); + }); +}); diff --git a/packages/ecs-client/tsconfig.json b/modules/input/tsconfig.json similarity index 100% rename from packages/ecs-client/tsconfig.json rename to modules/input/tsconfig.json diff --git a/packages/ecs-lib/tsconfig.spec.json b/modules/input/tsconfig.spec.json similarity index 100% rename from packages/ecs-lib/tsconfig.spec.json rename to modules/input/tsconfig.spec.json diff --git a/packages/ecs-client/tsdoc.json b/modules/input/tsdoc.json similarity index 100% rename from packages/ecs-client/tsdoc.json rename to modules/input/tsdoc.json diff --git a/packages/core-editor/tsdown.config.ts b/modules/input/tsdown.config.ts similarity index 100% rename from packages/core-editor/tsdown.config.ts rename to modules/input/tsdown.config.ts diff --git a/packages/music/.cliff-jumperrc.json b/modules/music/.cliff-jumperrc.json similarity index 86% rename from packages/music/.cliff-jumperrc.json rename to modules/music/.cliff-jumperrc.json index c81ff1b4..40d327ec 100644 --- a/packages/music/.cliff-jumperrc.json +++ b/modules/music/.cliff-jumperrc.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", "name": "music", "org": "nanoforge-dev", - "packagePath": "packages/music", + "packagePath": "modules/music", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/network-server/.gitignore b/modules/music/.gitignore similarity index 100% rename from packages/network-server/.gitignore rename to modules/music/.gitignore diff --git a/packages/graphics-2d/.prettierignore b/modules/music/.prettierignore similarity index 100% rename from packages/graphics-2d/.prettierignore rename to modules/music/.prettierignore diff --git a/modules/music/CHANGELOG.md b/modules/music/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/music/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/ecs-lib/LICENSE b/modules/music/LICENSE similarity index 97% rename from packages/ecs-lib/LICENSE rename to modules/music/LICENSE index 62c6400b..46724861 100644 --- a/packages/ecs-lib/LICENSE +++ b/modules/music/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/music/README.md b/modules/music/README.md similarity index 63% rename from packages/music/README.md rename to modules/music/README.md index 6cf40351..40e0b087 100644 --- a/packages/music/README.md +++ b/modules/music/README.md @@ -8,18 +8,18 @@ npm version npm downloads Tests status - Last commit + Last commit Contributors

## About -`@nanoforge-dev/music` is a music player for your game. +`@nanoforge-dev/music` is NanoForge's built-in music library. It manages a collection of named `HTMLAudioElement` tracks exposed on `Context.music` and ensures only one track plays at a time — starting a new track pauses whichever one was playing. ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/music @@ -30,44 +30,29 @@ bun add @nanoforge-dev/music ## Example usage -Initialize the library in your main file +Register `MusicLibrary` on your client app: ```ts -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { type IRunClientOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; import { MusicLibrary } from "@nanoforge-dev/music"; -export const MUSIC_SYM = Symbol("music"); - -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const assetManager = new AssetManagerLibrary(); - const music = new MusicLibrary(); - - app.useAssetManager(assetManager); - app.use(MUSIC_SYM, music); - - await app.init(options); - - music.load("music", assetManager.getAsset("/path/to/music.mp3").path); - - await app.run(); -} +app.use(new MusicLibrary()); ``` -Use to play music +Load and play tracks through `Context.music`: ```ts -export function mySystem(registry: Registry, ctx: Context) { - const assetManager = ctx.libs.getAssetManager(); - const music = ctx.libs.get(MUSIC_SYM); +public override async __init(): Promise { + ctx.music.load("menu", "/assets/menu.mp3"); + ctx.music.load("level-1", "/assets/level-1.mp3"); +} - music.play("music"); +public override async __run(ctx: Context): Promise { + if (levelStarted) ctx.music.play("level-1"); // stops "menu" automatically } ``` +Call `ctx.music.mute()` to toggle the muted state of every loaded track. `play` throws `NfNotFound` when the given key was never loaded. + ## Links - [GitHub][source] @@ -85,6 +70,6 @@ If you don't understand something in the documentation, you are experiencing pro [documentation]: https://github.com/NanoForge-dev/Engine [discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/music +[source]: https://github.com/NanoForge-dev/Engine/tree/main/modules/music [npm]: https://www.npmjs.com/package/@nanoforge-dev/music [contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/ecs-lib/cliff.toml b/modules/music/cliff.toml similarity index 100% rename from packages/ecs-lib/cliff.toml rename to modules/music/cliff.toml diff --git a/packages/graphics-2d-editor/eslint.config.js b/modules/music/eslint.config.js similarity index 100% rename from packages/graphics-2d-editor/eslint.config.js rename to modules/music/eslint.config.js diff --git a/packages/music/mint-tsdocs.config.json b/modules/music/mint-tsdocs.config.json similarity index 100% rename from packages/music/mint-tsdocs.config.json rename to modules/music/mint-tsdocs.config.json diff --git a/packages/music/package.json b/modules/music/package.json similarity index 91% rename from packages/music/package.json rename to modules/music/package.json index f5dfed97..cf504e05 100644 --- a/packages/music/package.json +++ b/modules/music/package.json @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -43,7 +44,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/music" + "directory": "modules/music" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -52,7 +53,7 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/music/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/music/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, @@ -71,7 +72,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/ecs-server/prettier.config.js b/modules/music/prettier.config.js similarity index 100% rename from packages/ecs-server/prettier.config.js rename to modules/music/prettier.config.js diff --git a/modules/music/src/context-augmentation.ts b/modules/music/src/context-augmentation.ts new file mode 100644 index 00000000..7111a651 --- /dev/null +++ b/modules/music/src/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { MusicContextApi } from "./music-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + music: MusicContextApi; + } +} diff --git a/modules/music/src/index.ts b/modules/music/src/index.ts new file mode 100644 index 00000000..b6ebf51e --- /dev/null +++ b/modules/music/src/index.ts @@ -0,0 +1,4 @@ +import "./context-augmentation"; + +export type { MusicContextApi } from "./music-context.type"; +export { MusicLibrary } from "./music.library"; diff --git a/modules/music/src/music-context.type.ts b/modules/music/src/music-context.type.ts new file mode 100644 index 00000000..d1d79af4 --- /dev/null +++ b/modules/music/src/music-context.type.ts @@ -0,0 +1,9 @@ +/** Public surface of `MusicLibrary`, exposed on `Context.music`. */ +export interface MusicContextApi { + /** Registers a music track under a unique key, loaded from `file`. */ + load(key: string, file: string): void; + /** Stops the currently playing track (if any) and starts the requested one. */ + play(key: string): void; + /** Toggles the muted state of every loaded track. */ + mute(): void; +} diff --git a/modules/music/src/music.library.ts b/modules/music/src/music.library.ts new file mode 100644 index 00000000..2ac36a09 --- /dev/null +++ b/modules/music/src/music.library.ts @@ -0,0 +1,81 @@ +import { Library, NfNotFound, defineLibraryKey } from "@nanoforge-dev/common"; + +import type { MusicContextApi } from "./music-context.type"; + +/** + * Built-in music library. + * + * @remarks + * Manages a collection of named `HTMLAudioElement` instances and ensures + * only one track plays at a time — unlike `SoundLibrary`, starting a new + * track pauses whichever one was playing. + */ +export class MusicLibrary extends Library { + readonly key = defineLibraryKey("music"); + + private _muted = true; + private _tracks?: Map; + private _current: HTMLAudioElement | null = null; + + public override async __init(): Promise { + this._tracks = new Map(); + this._muted = true; + this._current = null; + } + + public override async __clear(): Promise { + this._current?.pause(); + this._current = null; + for (const element of this._tracks?.values() ?? []) element.pause(); + this._tracks?.clear(); + } + + /** + * Registers a music track under a unique key. + * + * @remarks + * Creates an `HTMLAudioElement` from the given URL. The track respects + * the current muted state at load time. + */ + public load(key: string, file: string): void { + if (!this._tracks) this.throwNotInitializedError(); + const element = new Audio(file); + element.muted = this._muted; + this._tracks.set(key, element); + } + + /** + * @throws `NfNotFound` When no track is registered under the given key. + */ + public play(key: string): void { + if (!this._tracks) this.throwNotInitializedError(); + const element = this._tracks.get(key); + if (!element) { + this._current = null; + throw new NfNotFound(key); + } + + this._current?.pause(); + this._current = element; + this._current.play().catch((error: unknown) => { + console.error(`Got error: ${error}`); + }); + } + + /** Toggles the muted state of every loaded track. */ + public mute(): void { + if (!this._tracks) this.throwNotInitializedError(); + this._muted = !this._muted; + for (const element of this._tracks.values()) element.muted = this._muted; + } + + public override expose(): MusicContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + load: (key, file) => library.load(key, file), + play: (key) => library.play(key), + mute: () => library.mute(), + }; + } +} diff --git a/packages/music/test/music.library.spec.ts b/modules/music/test/music.library.spec.ts similarity index 63% rename from packages/music/test/music.library.spec.ts rename to modules/music/test/music.library.spec.ts index 56f2b4cd..1351793e 100644 --- a/packages/music/test/music.library.spec.ts +++ b/modules/music/test/music.library.spec.ts @@ -23,24 +23,16 @@ const makeMockAudio = () => { describe("MusicLibrary", () => { describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new MusicLibrary().__name).toBe("NfMusic"); + it("should expose the reserved 'music' key", () => { + expect(new MusicLibrary().key).toBe("music"); }); }); describe("before initialization", () => { - it("should throw when play is called before __init", () => { + it("should throw when play/mute/load are called before __init", () => { const library = new MusicLibrary(); expect(() => library.play("theme")).toThrow(); - }); - - it("should throw when mute is called before __init", () => { - const library = new MusicLibrary(); expect(() => library.mute()).toThrow(); - }); - - it("should throw when load is called before __init", () => { - const library = new MusicLibrary(); expect(() => library.load("theme", "theme.mp3")).toThrow(); }); }); @@ -64,11 +56,6 @@ describe("MusicLibrary", () => { expect(() => library.play("unknown")).toThrow(NfNotFound); }); - it("should play a loaded track without error", () => { - library.load("theme", "theme.mp3"); - expect(() => library.play("theme")).not.toThrow(); - }); - it("should call play on the audio element", () => { library.load("theme", "theme.mp3"); library.play("theme"); @@ -83,14 +70,6 @@ describe("MusicLibrary", () => { expect(mock.pause).toHaveBeenCalled(); }); - it("should toggle mute state for all loaded tracks", async () => { - library.load("theme", "theme.mp3"); - library.load("battle", "battle.mp3"); - library.mute(); - library.load("credits", "credits.mp3"); - expect(() => library.play("credits")).not.toThrow(); - }); - it("should load multiple tracks independently", () => { library.load("theme", "theme.mp3"); library.load("battle", "battle.mp3"); @@ -98,9 +77,46 @@ describe("MusicLibrary", () => { expect(() => library.play("battle")).not.toThrow(); }); - it("should throw NfNotFound after loading a different track", () => { + it("should clear the current track when play() fails", () => { + library.load("theme", "theme.mp3"); + library.play("theme"); + expect(() => library.play("unknown")).toThrow(NfNotFound); + }); + }); + + describe("__clear", () => { + it("pauses the current track and clears every loaded track", async () => { + const mock = makeMockAudio(); + vi.stubGlobal("Audio", mock.AudioClass); + const library = new MusicLibrary(); + await library.__init(); library.load("theme", "theme.mp3"); - expect(() => library.play("credits")).toThrow(NfNotFound); + library.play("theme"); + + await library.__clear({} as any); + + expect(mock.pause).toHaveBeenCalled(); + expect(() => library.play("theme")).toThrow(NfNotFound); + vi.unstubAllGlobals(); + }); + + it("does not throw when called before __init", async () => { + await expect(new MusicLibrary().__clear({} as any)).resolves.toBeUndefined(); + }); + }); + + describe("expose", () => { + it("returns methods that behave like the instance methods", async () => { + const mock = makeMockAudio(); + vi.stubGlobal("Audio", mock.AudioClass); + const library = new MusicLibrary(); + await library.__init(); + + library.expose().load("theme", "theme.mp3"); + library.expose().play("theme"); + + expect(mock.play).toHaveBeenCalled(); + vi.unstubAllGlobals(); }); }); }); diff --git a/packages/ecs-lib/tsconfig.json b/modules/music/tsconfig.json similarity index 100% rename from packages/ecs-lib/tsconfig.json rename to modules/music/tsconfig.json diff --git a/packages/ecs-server/tsconfig.spec.json b/modules/music/tsconfig.spec.json similarity index 100% rename from packages/ecs-server/tsconfig.spec.json rename to modules/music/tsconfig.spec.json diff --git a/packages/ecs-lib/tsdoc.json b/modules/music/tsdoc.json similarity index 100% rename from packages/ecs-lib/tsdoc.json rename to modules/music/tsdoc.json diff --git a/packages/ecs-client/tsdown.config.ts b/modules/music/tsdown.config.ts similarity index 100% rename from packages/ecs-client/tsdown.config.ts rename to modules/music/tsdown.config.ts diff --git a/packages/sound/.cliff-jumperrc.json b/modules/sound/.cliff-jumperrc.json similarity index 86% rename from packages/sound/.cliff-jumperrc.json rename to modules/sound/.cliff-jumperrc.json index df5cffc2..7679c0e9 100644 --- a/packages/sound/.cliff-jumperrc.json +++ b/modules/sound/.cliff-jumperrc.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/favware/cliff-jumper/main/assets/cliff-jumper.schema.json", "name": "sound", "org": "nanoforge-dev", - "packagePath": "packages/sound", + "packagePath": "modules/sound", "tagTemplate": "{{new-version}}", "identifierBase": false } diff --git a/packages/graphics-2d/.gitignore b/modules/sound/.gitignore similarity index 93% rename from packages/graphics-2d/.gitignore rename to modules/sound/.gitignore index e56e932b..88ef62e8 100644 --- a/packages/graphics-2d/.gitignore +++ b/modules/sound/.gitignore @@ -12,40 +12,6 @@ # 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 @@ -257,8 +223,6 @@ dist .yarn/install-state.gz .pnp.* -### Private - # Turbo .turbo/ diff --git a/packages/music/.prettierignore b/modules/sound/.prettierignore similarity index 100% rename from packages/music/.prettierignore rename to modules/sound/.prettierignore diff --git a/modules/sound/CHANGELOG.md b/modules/sound/CHANGELOG.md new file mode 100644 index 00000000..6361e43e --- /dev/null +++ b/modules/sound/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. diff --git a/packages/ecs-server/LICENSE b/modules/sound/LICENSE similarity index 97% rename from packages/ecs-server/LICENSE rename to modules/sound/LICENSE index 62c6400b..46724861 100644 --- a/packages/ecs-server/LICENSE +++ b/modules/sound/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/sound/README.md b/modules/sound/README.md similarity index 64% rename from packages/sound/README.md rename to modules/sound/README.md index 63e83f28..f5495590 100644 --- a/packages/sound/README.md +++ b/modules/sound/README.md @@ -8,18 +8,18 @@ npm version npm downloads Tests status - Last commit + Last commit Contributors

## About -`@nanoforge-dev/sound` is a sound manager for your game. +`@nanoforge-dev/sound` is NanoForge's built-in sound-effect library. It manages a collection of named `HTMLAudioElement` instances exposed on `Context.sound`. Unlike `@nanoforge-dev/music`, multiple sounds may overlap — there's no single-track exclusivity. ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/sound @@ -30,42 +30,29 @@ bun add @nanoforge-dev/sound ## Example usage -Initialize the library in your main file +Register `SoundLibrary` on your client app: ```ts -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { type IRunClientOptions } from "@nanoforge-dev/common"; -import { NanoforgeFactory } from "@nanoforge-dev/core"; import { SoundLibrary } from "@nanoforge-dev/sound"; -export async function main(options: IRunClientOptions) { - const app = NanoforgeFactory.createClient(); - - const assetManager = new AssetManagerLibrary(); - const sound = new SoundLibrary(); - - app.useAssetManager(assetManager); - app.useSound(sound); - - await app.init(options); - - sound.load("sound", assetManager.getAssetPath("/path/to/sound.mp3").path); - - await app.run(); -} +app.use(new SoundLibrary()); ``` -Use to play sound +Load and play sound effects through `Context.sound`: ```ts -export function mySystem(registry: Registry, ctx: Context) { - const assetManager = ctx.libs.getAssetManager(); - const sound = ctx.libs.getSound(); +public override async __init(): Promise { + ctx.sound.load("jump", "/assets/jump.wav"); + ctx.sound.load("hit", "/assets/hit.wav"); +} - sound.play("sound"); +public override async __run(ctx: Context): Promise { + if (playerJumped) ctx.sound.play("jump"); } ``` +Call `ctx.sound.mute()` to toggle the muted state of every loaded sound effect. `play` throws `NfNotFound` when the given key was never loaded. + ## Links - [GitHub][source] @@ -83,6 +70,6 @@ If you don't understand something in the documentation, you are experiencing pro [documentation]: https://github.com/NanoForge-dev/Engine [discussions]: https://github.com/NanoForge-dev/Engine/discussions -[source]: https://github.com/NanoForge-dev/Engine/tree/main/packages/sound +[source]: https://github.com/NanoForge-dev/Engine/tree/main/modules/sound [npm]: https://www.npmjs.com/package/@nanoforge-dev/sound [contributing]: https://github.com/NanoForge-dev/Engine/blob/main/.github/CONTRIBUTING.md diff --git a/packages/graphics-2d-editor/cliff.toml b/modules/sound/cliff.toml similarity index 100% rename from packages/graphics-2d-editor/cliff.toml rename to modules/sound/cliff.toml diff --git a/packages/input/eslint.config.js b/modules/sound/eslint.config.js similarity index 100% rename from packages/input/eslint.config.js rename to modules/sound/eslint.config.js diff --git a/packages/sound/mint-tsdocs.config.json b/modules/sound/mint-tsdocs.config.json similarity index 100% rename from packages/sound/mint-tsdocs.config.json rename to modules/sound/mint-tsdocs.config.json diff --git a/packages/sound/package.json b/modules/sound/package.json similarity index 91% rename from packages/sound/package.json rename to modules/sound/package.json index e64a4193..e517761f 100644 --- a/packages/sound/package.json +++ b/modules/sound/package.json @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -43,7 +44,7 @@ "repository": { "type": "git", "url": "git+https://github.com/NanoForge-dev/Engine.git", - "directory": "packages/sound" + "directory": "modules/sound" }, "funding": "https://github.com/NanoForge-dev/Engine?sponsor", "scripts": { @@ -52,7 +53,7 @@ "format": "prettier --write . && eslint --fix --format=pretty src", "test:unit": "vitest run --config ../../vitest.config.ts", "prepack": "pnpm run build && pnpm run lint", - "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/sound/*'", + "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'modules/sound/*'", "release": "cliff-jumper", "docs": "mint-tsdocs generate" }, @@ -71,7 +72,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/graphics-2d/prettier.config.js b/modules/sound/prettier.config.js similarity index 100% rename from packages/graphics-2d/prettier.config.js rename to modules/sound/prettier.config.js diff --git a/modules/sound/src/context-augmentation.ts b/modules/sound/src/context-augmentation.ts new file mode 100644 index 00000000..25325310 --- /dev/null +++ b/modules/sound/src/context-augmentation.ts @@ -0,0 +1,7 @@ +import type { SoundContextApi } from "./sound-context.type"; + +declare module "@nanoforge-dev/common" { + interface Context { + sound: SoundContextApi; + } +} diff --git a/modules/sound/src/index.ts b/modules/sound/src/index.ts new file mode 100644 index 00000000..14d89656 --- /dev/null +++ b/modules/sound/src/index.ts @@ -0,0 +1,4 @@ +import "./context-augmentation"; + +export type { SoundContextApi } from "./sound-context.type"; +export { SoundLibrary } from "./sound.library"; diff --git a/modules/sound/src/sound-context.type.ts b/modules/sound/src/sound-context.type.ts new file mode 100644 index 00000000..d967516d --- /dev/null +++ b/modules/sound/src/sound-context.type.ts @@ -0,0 +1,9 @@ +/** Public surface of `SoundLibrary`, exposed on `Context.sound`. */ +export interface SoundContextApi { + /** Registers a sound effect under a unique key, loaded from `file`. */ + load(key: string, file: string): void; + /** Plays a previously loaded sound effect. Multiple sounds may overlap. */ + play(key: string): void; + /** Toggles the muted state of every loaded sound effect. */ + mute(): void; +} diff --git a/modules/sound/src/sound.library.ts b/modules/sound/src/sound.library.ts new file mode 100644 index 00000000..5d32c713 --- /dev/null +++ b/modules/sound/src/sound.library.ts @@ -0,0 +1,72 @@ +import { Library, NfNotFound, defineLibraryKey } from "@nanoforge-dev/common"; + +import type { SoundContextApi } from "./sound-context.type"; + +/** + * Built-in sound-effect library. + * + * @remarks + * Manages a collection of named `HTMLAudioElement` instances. Load sounds + * with `load` and trigger playback with `play`. Unlike `MusicLibrary`, + * multiple sounds may overlap — there's no single-track exclusivity. + */ +export class SoundLibrary extends Library { + readonly key = defineLibraryKey("sound"); + + private _muted = true; + private _sounds?: Map; + + public override async __init(): Promise { + this._sounds = new Map(); + this._muted = true; + } + + public override async __clear(): Promise { + for (const element of this._sounds?.values() ?? []) element.pause(); + this._sounds?.clear(); + } + + /** + * Registers a sound effect under a unique key. + * + * @remarks + * Creates an `HTMLAudioElement` from the given URL. The sound respects + * the current muted state at load time. + */ + public load(key: string, file: string): void { + if (!this._sounds) this.throwNotInitializedError(); + const element = new Audio(file); + element.muted = this._muted; + this._sounds.set(key, element); + } + + /** + * @throws `NfNotFound` When no sound is registered under the given key. + */ + public play(key: string): void { + if (!this._sounds) this.throwNotInitializedError(); + const element = this._sounds.get(key); + if (!element) throw new NfNotFound(key); + + element.play().catch((error: unknown) => { + console.error(`Got error: ${error}`); + }); + } + + /** Toggles the muted state of every loaded sound effect. */ + public mute(): void { + if (!this._sounds) this.throwNotInitializedError(); + this._muted = !this._muted; + for (const element of this._sounds.values()) element.muted = this._muted; + } + + public override expose(): SoundContextApi { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const library = this; + return { + load: (key, file) => library.load(key, file), + play: (key) => library.play(key), + mute: () => library.mute(), + }; + } +} diff --git a/packages/sound/test/sound.library.spec.ts b/modules/sound/test/sound.library.spec.ts similarity index 56% rename from packages/sound/test/sound.library.spec.ts rename to modules/sound/test/sound.library.spec.ts index da5725c2..37493c67 100644 --- a/packages/sound/test/sound.library.spec.ts +++ b/modules/sound/test/sound.library.spec.ts @@ -23,24 +23,16 @@ const makeMockAudio = () => { describe("SoundLibrary", () => { describe("metadata", () => { - it("should expose the correct library name", () => { - expect(new SoundLibrary().__name).toBe("NfSound"); + it("should expose the reserved 'sound' key", () => { + expect(new SoundLibrary().key).toBe("sound"); }); }); describe("before initialization", () => { - it("should throw when play is called before __init", () => { + it("should throw when play/mute/load are called before __init", () => { const library = new SoundLibrary(); expect(() => library.play("click")).toThrow(); - }); - - it("should throw when mute is called before __init", () => { - const library = new SoundLibrary(); expect(() => library.mute()).toThrow(); - }); - - it("should throw when load is called before __init", () => { - const library = new SoundLibrary(); expect(() => library.load("click", "click.mp3")).toThrow(); }); }); @@ -64,34 +56,67 @@ describe("SoundLibrary", () => { expect(() => library.play("unknown")).toThrow(NfNotFound); }); - it("should play a loaded sound without error", () => { - library.load("click", "click.mp3"); - expect(() => library.play("click")).not.toThrow(); - }); - it("should call play on the audio element", () => { library.load("click", "click.mp3"); library.play("click"); expect(mock.play).toHaveBeenCalled(); }); - it("should start muted and toggle mute state", async () => { + it("should load multiple sounds independently, without exclusivity", () => { library.load("click", "click.mp3"); - library.mute(); + library.load("boom", "boom.mp3"); + expect(() => library.play("click")).not.toThrow(); + expect(() => library.play("boom")).not.toThrow(); + expect(mock.pause).not.toHaveBeenCalled(); + }); + + it("should apply the current muted state to newly loaded sounds", () => { + library.mute(); // now unmuted (starts muted) library.load("beep", "beep.mp3"); - expect(() => library.play("beep")).not.toThrow(); + expect(mock.AudioClass).toBeTruthy(); }); - it("should load multiple sounds independently", () => { + it("should toggle mute for every already-loaded sound", () => { library.load("click", "click.mp3"); - library.load("boom", "boom.mp3"); + library.mute(); + library.mute(); + // two toggles returns to the original (muted) state — no throw is the contract here. expect(() => library.play("click")).not.toThrow(); - expect(() => library.play("boom")).not.toThrow(); }); + }); - it("should throw NfNotFound after loading a different sound", () => { + describe("__clear", () => { + it("pauses and clears every loaded sound", async () => { + const mock = makeMockAudio(); + vi.stubGlobal("Audio", mock.AudioClass); + const library = new SoundLibrary(); + await library.__init(); library.load("click", "click.mp3"); - expect(() => library.play("boom")).toThrow(NfNotFound); + + await library.__clear({} as any); + + expect(mock.pause).toHaveBeenCalled(); + expect(() => library.play("click")).toThrow(NfNotFound); + vi.unstubAllGlobals(); + }); + + it("does not throw when called before __init", async () => { + await expect(new SoundLibrary().__clear({} as any)).resolves.toBeUndefined(); + }); + }); + + describe("expose", () => { + it("returns methods that behave like the instance methods", async () => { + const mock = makeMockAudio(); + vi.stubGlobal("Audio", mock.AudioClass); + const library = new SoundLibrary(); + await library.__init(); + + library.expose().load("click", "click.mp3"); + library.expose().play("click"); + + expect(mock.play).toHaveBeenCalled(); + vi.unstubAllGlobals(); }); }); }); diff --git a/packages/graphics-2d/tsconfig.json b/modules/sound/tsconfig.json similarity index 100% rename from packages/graphics-2d/tsconfig.json rename to modules/sound/tsconfig.json diff --git a/packages/graphics-2d/tsconfig.spec.json b/modules/sound/tsconfig.spec.json similarity index 100% rename from packages/graphics-2d/tsconfig.spec.json rename to modules/sound/tsconfig.spec.json diff --git a/packages/graphics-2d-editor/tsdoc.json b/modules/sound/tsdoc.json similarity index 100% rename from packages/graphics-2d-editor/tsdoc.json rename to modules/sound/tsdoc.json diff --git a/packages/ecs-lib/tsdown.config.ts b/modules/sound/tsdown.config.ts similarity index 100% rename from packages/ecs-lib/tsdown.config.ts rename to modules/sound/tsdown.config.ts From 5628b62b9e92e4ce50a4b4de1bc11139b79892d0 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 17:32:10 +0200 Subject: [PATCH 10/12] feat: add new core (#424) --- packages/core/.nvmrc | 1 - packages/core/LICENSE | 2 +- packages/core/README.md | 2 +- packages/core/package.json | 12 +- .../src/application/application-config.ts | 89 ------- .../application/application-options.type.ts | 6 +- .../src/application/nanoforge-application.ts | 147 +++++------ .../core/src/application/nanoforge-client.ts | 43 +-- .../core/src/application/nanoforge-factory.ts | 14 +- .../core/src/application/nanoforge-server.ts | 24 +- .../contexts/application.editable-context.ts | 20 -- .../executions/clear.editable-context.ts | 3 - .../executions/execution.editable-context.ts | 3 - .../executions/init.editable-context.ts | 3 - .../contexts/library.editable-context.ts | 7 - .../common/library/manager/library.manager.ts | 106 -------- .../common/library/relationship-functions.ts | 122 --------- packages/core/src/config/config-registry.ts | 19 -- packages/core/src/core/core.ts | 104 -------- packages/core/src/index.ts | 4 +- .../core/src/internal/internal-app-state.ts | 68 +++++ .../core/src/internal/internal-vars-state.ts | 25 ++ .../src/library-registry/library-registry.ts | 59 +++++ .../core/src/library-registry/ordering.ts | 55 ++++ packages/core/test/config-registry.spec.ts | 54 ---- .../test/editable-library-manager.spec.ts | 182 ------------- packages/core/test/internal-app-state.spec.ts | 60 +++++ .../core/test/internal-vars-state.spec.ts | 21 ++ .../core/test/nanoforge-application.spec.ts | 249 ++++++++++++++++++ packages/core/test/nanoforge-factory.spec.ts | 17 ++ packages/core/test/ordering.spec.ts | 79 ++++++ packages/core/test/relationship.spec.ts | 135 ---------- 32 files changed, 756 insertions(+), 979 deletions(-) delete mode 100644 packages/core/.nvmrc delete mode 100644 packages/core/src/application/application-config.ts delete mode 100644 packages/core/src/common/context/contexts/application.editable-context.ts delete mode 100644 packages/core/src/common/context/contexts/executions/clear.editable-context.ts delete mode 100644 packages/core/src/common/context/contexts/executions/execution.editable-context.ts delete mode 100644 packages/core/src/common/context/contexts/executions/init.editable-context.ts delete mode 100644 packages/core/src/common/context/contexts/library.editable-context.ts delete mode 100644 packages/core/src/common/library/manager/library.manager.ts delete mode 100644 packages/core/src/common/library/relationship-functions.ts delete mode 100644 packages/core/src/config/config-registry.ts delete mode 100644 packages/core/src/core/core.ts create mode 100644 packages/core/src/internal/internal-app-state.ts create mode 100644 packages/core/src/internal/internal-vars-state.ts create mode 100644 packages/core/src/library-registry/library-registry.ts create mode 100644 packages/core/src/library-registry/ordering.ts delete mode 100644 packages/core/test/config-registry.spec.ts delete mode 100644 packages/core/test/editable-library-manager.spec.ts create mode 100644 packages/core/test/internal-app-state.spec.ts create mode 100644 packages/core/test/internal-vars-state.spec.ts create mode 100644 packages/core/test/nanoforge-application.spec.ts create mode 100644 packages/core/test/nanoforge-factory.spec.ts create mode 100644 packages/core/test/ordering.spec.ts delete mode 100644 packages/core/test/relationship.spec.ts diff --git a/packages/core/.nvmrc b/packages/core/.nvmrc deleted file mode 100644 index 4aa0e0a7..00000000 --- a/packages/core/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v26 diff --git a/packages/core/LICENSE b/packages/core/LICENSE index 62c6400b..46724861 100644 --- a/packages/core/LICENSE +++ b/packages/core/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/core/README.md b/packages/core/README.md index c6579dfe..0833b3b1 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -19,7 +19,7 @@ ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install @nanoforge-dev/core diff --git a/packages/core/package.json b/packages/core/package.json index efd95ea4..b8003f3f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -13,8 +13,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -57,11 +58,8 @@ "docs": "mint-tsdocs generate" }, "dependencies": { - "@nanoforge-dev/asset-manager": "workspace:*", - "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/input": "workspace:*", - "class-transformer": "catalog:config", - "class-validator": "catalog:config" + "@nanoforge-dev/asset": "workspace:*", + "@nanoforge-dev/common": "workspace:*" }, "devDependencies": { "@favware/cliff-jumper": "catalog:ci", @@ -75,7 +73,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/core/src/application/application-config.ts b/packages/core/src/application/application-config.ts deleted file mode 100644 index 7eeede0c..00000000 --- a/packages/core/src/application/application-config.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { - type IAssetManagerLibrary, - type IComponentSystemLibrary, - type IGraphicsLibrary, - type IInputLibrary, - type ILibrary, - type IMusicLibrary, - type INetworkLibrary, - type ISoundLibrary, - type LibraryHandle, -} from "@nanoforge-dev/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); - } - - public getSoundLibrary() { - return this._libraryManager.getSound(); - } - - public useSoundLibrary(library: ISoundLibrary) { - this._libraryManager.setSound(library); - } - - public getMusicLibrary() { - return this._libraryManager.getMusic(); - } - - public useMusicLibrary(library: IMusicLibrary) { - this._libraryManager.setMusic(library); - } -} diff --git a/packages/core/src/application/application-options.type.ts b/packages/core/src/application/application-options.type.ts index 071d99ab..c3f4ab06 100644 --- a/packages/core/src/application/application-options.type.ts +++ b/packages/core/src/application/application-options.type.ts @@ -2,7 +2,7 @@ * Options accepted by `NanoforgeFactory.createClient` and * `NanoforgeFactory.createServer`. */ -export interface IApplicationOptions { +export interface ApplicationOptions { /** * Target game-loop frequency in ticks per second. * @@ -10,3 +10,7 @@ export interface IApplicationOptions { */ tickRate: number; } + +export const DEFAULT_APPLICATION_OPTIONS: ApplicationOptions = { + tickRate: 60, +}; diff --git a/packages/core/src/application/nanoforge-application.ts b/packages/core/src/application/nanoforge-application.ts index 0c650f45..96eb9d21 100644 --- a/packages/core/src/application/nanoforge-application.ts +++ b/packages/core/src/application/nanoforge-application.ts @@ -1,16 +1,17 @@ +import { AssetLibrary } from "@nanoforge-dev/asset"; import { - type IAssetManagerLibrary, - type IComponentSystemLibrary, - type ILibrary, - type INetworkLibrary, - type IRunOptions, + type ClientRunOptions, + type Context, + type InitContext, + type Library, NfNotInitializedException, + type RunOptions, } from "@nanoforge-dev/common"; -import { EditableApplicationContext } from "../common/context/contexts/application.editable-context"; -import { Core } from "../core/core"; -import { ApplicationConfig } from "./application-config"; -import type { IApplicationOptions } from "./application-options.type"; +import { InternalAppState } from "../internal/internal-app-state"; +import { InternalVarsState } from "../internal/internal-vars-state"; +import { LibraryRegistry } from "../library-registry/library-registry"; +import { type ApplicationOptions, DEFAULT_APPLICATION_OPTIONS } from "./application-options.type"; /** * Base class for client and server NanoForge applications. @@ -30,81 +31,34 @@ import type { IApplicationOptions } from "./application-options.type"; * ``` */ export abstract class NanoforgeApplication { - protected applicationConfig: ApplicationConfig; - private _core?: Core; - private readonly _options: IApplicationOptions; + private readonly registry = new LibraryRegistry(); + private readonly appState: InternalAppState; + private readonly varsState = new InternalVarsState(); + private readonly options: ApplicationOptions; + + private context?: Context; /** * @param options - Optional application-level settings such as tickRate. */ - constructor(options?: Partial) { - this.applicationConfig = new ApplicationConfig(); - - this._options = { - tickRate: 60, - ...(options ?? {}), - }; + constructor(options?: Partial) { + this.options = { ...DEFAULT_APPLICATION_OPTIONS, ...options }; + this.appState = new InternalAppState(this.options.tickRate); + this.registry.registerBuiltin(new AssetLibrary()); } /** - * Register a library under a custom symbol. - * - * @remarks - * Use this method for libraries that do not have a dedicated shorthand (e.g. - * game-specific custom libraries). For built-in library types prefer the - * typed helpers such as `useAssetManager`, `useNetwork`, etc. + * Registers a library. Single argument — the library owns its own + * context key (see `defineLibraryKey`). * - * @param sym - Unique symbol identifying the library slot. * @param library - Library instance to register. - */ - public use(sym: symbol, library: ILibrary): void { - this.applicationConfig.useLibrary(sym, library); - } - - /** - * Register the component-system (ECS) library. - * - * @param library - ECS library instance (e.g. ECSClientLibrary or ECSServerLibrary). - */ - public useComponentSystem(library: IComponentSystemLibrary) { - this.applicationConfig.useComponentSystemLibrary(library); - } - - /** - * Register the network library. - * - * @param library - Network library instance (e.g. NetworkClientLibrary or NetworkServerLibrary). - */ - public useNetwork(library: INetworkLibrary) { - this.applicationConfig.useNetworkLibrary(library); - } - - /** - * Register the asset-manager library. - * - * @param library - Asset manager instance (e.g. AssetManagerLibrary). - */ - public useAssetManager(library: IAssetManagerLibrary) { - this.applicationConfig.useAssetManagerLibrary(library); - } - - /** - * Initialise all registered libraries in dependency order and prepare the - * engine for the game loop. - * - * @remarks - * Must be called before `run`. Resolves once every library's `__init` - * hook has completed. * - * @param options - Run options providing the canvas container, files map, and - * environment variables. + * @throws {@link NfDuplicateLibraryException} If the key is already + * registered or reserved (`"app"`, `"vars"`, `"assets"`). */ - public init(options: IRunOptions): Promise { - this._core = new Core( - this.applicationConfig, - new EditableApplicationContext(this.applicationConfig.libraryManager), - ); - return this._core.init(options, this._options); + public use(library: L): void { + if (this.context) throw new Error("Cannot register libraries after init() has been called."); + this.registry.register(library); } /** @@ -115,8 +69,49 @@ export abstract class NanoforgeApplication { * * @throws `NfNotInitializedException` When called before `init`. */ - public run() { - if (!this._core) throw new NfNotInitializedException("Core"); - return this._core?.run(); + public async run(): Promise { + if (!this.context) throw new NfNotInitializedException("NanoforgeApplication"); + const context = this.context; + const orderedForRun = this.registry.getOrderedForRun(); + + const tickLengthMs = 1000 / this.options.tickRate; + let previousTick = Date.now(); + + const loop = async (): Promise => { + if (!context.app.isRunning) { + for (const library of orderedForRun) await library.__clear(context); + return; + } + + const tickStart = Date.now(); + + for (const library of orderedForRun) await library.__events(context); + + if (context.app.isPaused) { + previousTick = tickStart; + } else { + this.appState.setDelta(tickStart - previousTick); + for (const library of orderedForRun) await library.__run(context); + previousTick = tickStart; + } + + setTimeout(loop, tickLengthMs + tickStart - Date.now()); + }; + + this.appState.setIsRunning(true); + setTimeout(loop); + } + + protected async initialize(options: RunOptions | ClientRunOptions): Promise { + const initContext: InitContext = { ...options, vars: this.varsState.asVarsContext() }; + + for (const library of this.registry.getOrderedForInit()) { + await library.__init(initContext); + } + + this.context = this.registry.buildContext( + this.appState.asAppContext(), + this.varsState.asVarsContext(), + ); } } diff --git a/packages/core/src/application/nanoforge-client.ts b/packages/core/src/application/nanoforge-client.ts index 684e132f..bc86f454 100644 --- a/packages/core/src/application/nanoforge-client.ts +++ b/packages/core/src/application/nanoforge-client.ts @@ -1,8 +1,4 @@ -import { - type IGraphicsLibrary, - type IInputLibrary, - type ISoundLibrary, -} from "@nanoforge-dev/common"; +import type { ClientRunOptions } from "@nanoforge-dev/common"; import { NanoforgeApplication } from "./nanoforge-application"; @@ -17,39 +13,26 @@ import { NanoforgeApplication } from "./nanoforge-application"; * @example * ```ts * const client = NanoforgeFactory.createClient(); - * client.useAssetManager(new AssetManagerLibrary()); - * client.useGraphics(new Graphics2DLibrary()); - * client.useInput(new InputLibrary()); - * client.useSound(new SoundLibrary()); + * client.use(new Graphics2DLibrary()); + * client.use(new InputLibrary()); + * client.use(new SoundLibrary()); * await client.init(`container, files, env `); * client.run(); * ``` */ export class NanoforgeClient extends NanoforgeApplication { /** - * Register the graphics library used to render the game. + * Initialise all registered libraries in dependency order and prepare the + * engine for the game loop. * - * @param library - Graphics library instance (e.g. Graphics2DLibrary). - */ - public useGraphics(library: IGraphicsLibrary) { - this.applicationConfig.useGraphicsLibrary(library); - } - - /** - * Register the input library used to read keyboard and mouse state. - * - * @param library - Input library instance (e.g. InputLibrary). - */ - public useInput(library: IInputLibrary) { - this.applicationConfig.useInputLibrary(library); - } - - /** - * Register the sound-effect library. + * @remarks + * Must be called before `run`. Resolves once every library's `__init` + * hook has completed. * - * @param library - Sound library instance (e.g. SoundLibrary). + * @param options - Run options providing the canvas container, files map, and + * environment variables. */ - public useSound(library: ISoundLibrary) { - this.applicationConfig.useSoundLibrary(library); + public async init(options: ClientRunOptions): Promise { + await this.initialize(options); } } diff --git a/packages/core/src/application/nanoforge-factory.ts b/packages/core/src/application/nanoforge-factory.ts index 1c275243..50aadb1f 100644 --- a/packages/core/src/application/nanoforge-factory.ts +++ b/packages/core/src/application/nanoforge-factory.ts @@ -1,4 +1,4 @@ -import { type IApplicationOptions } from "./application-options.type"; +import type { ApplicationOptions } from "./application-options.type"; import { NanoforgeClient } from "./nanoforge-client"; import { NanoforgeServer } from "./nanoforge-server"; @@ -8,8 +8,7 @@ class NanoforgeFactoryStatic { * * @remarks * Returns a `NanoforgeClient` on which you can call - * `useGraphics`, `useInput`, `useSound`, `useAssetManager`, etc. before - * calling `init` and `run`. + * `use` before calling `init` and `run`. * * @param options - Optional application settings (e.g. tickRate). * @returns A pre-configured `NanoforgeClient` instance. @@ -19,7 +18,7 @@ class NanoforgeFactoryStatic { * const client = NanoforgeFactory.createClient(`tickRate: 60 `); * ``` */ - createClient(options?: Partial): NanoforgeClient { + createClient(options?: Partial): NanoforgeClient { return new NanoforgeClient(options); } @@ -28,8 +27,7 @@ class NanoforgeFactoryStatic { * * @remarks * Returns a `NanoforgeServer` on which you can call - * `useNetwork`, `useAssetManager`, `useComponentSystem`, etc. before calling - * `init` and `run`. + * `use` before calling `init` and `run`. * * @param options - Optional application settings (e.g. tickRate). * @returns A pre-configured `NanoforgeServer` instance. @@ -39,7 +37,7 @@ class NanoforgeFactoryStatic { * const server = NanoforgeFactory.createServer(`tickRate: 20 `); * ``` */ - createServer(options?: Partial): NanoforgeServer { + createServer(options?: Partial): NanoforgeServer { return new NanoforgeServer(options); } } @@ -54,8 +52,6 @@ class NanoforgeFactoryStatic { * * @example * ```ts - * import `NanoforgeFactory ` from "@nanoforge-dev/core"; - * * const client = NanoforgeFactory.createClient(); * ``` */ diff --git a/packages/core/src/application/nanoforge-server.ts b/packages/core/src/application/nanoforge-server.ts index 5612515b..fbac5f97 100644 --- a/packages/core/src/application/nanoforge-server.ts +++ b/packages/core/src/application/nanoforge-server.ts @@ -1,3 +1,5 @@ +import type { RunOptions } from "@nanoforge-dev/common"; + import { NanoforgeApplication } from "./nanoforge-application"; /** @@ -10,11 +12,25 @@ import { NanoforgeApplication } from "./nanoforge-application"; * @example * ```ts * const server = NanoforgeFactory.createServer(); - * server.useAssetManager(new AssetManagerLibrary()); - * server.useNetwork(new NetworkServerLibrary()); - * server.useComponentSystem(new ECSServerLibrary()); + * server.use(new NetworkServerLibrary()); + * server.use(new EcsLibrary()); * await server.init(`files, env `); * server.run(); * ``` */ -export class NanoforgeServer extends NanoforgeApplication {} +export class NanoforgeServer extends NanoforgeApplication { + /** + * Initialise all registered libraries in dependency order and prepare the + * engine for the game loop. + * + * @remarks + * Must be called before `run`. Resolves once every library's `__init` + * hook has completed. + * + * @param options - Run options providing the canvas container, files map, and + * environment variables. + */ + public async init(options: RunOptions): Promise { + await this.initialize(options); + } +} diff --git a/packages/core/src/common/context/contexts/application.editable-context.ts b/packages/core/src/common/context/contexts/application.editable-context.ts deleted file mode 100644 index 492b797e..00000000 --- a/packages/core/src/common/context/contexts/application.editable-context.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApplicationContext } from "@nanoforge-dev/common"; - -import { type EditableLibraryManager } from "../../library/manager/library.manager"; - -export class EditableApplicationContext extends ApplicationContext { - private _libraryManager: EditableLibraryManager; - - constructor(libraryManager: EditableLibraryManager) { - super(); - this._libraryManager = libraryManager; - } - - setDelta(delta: number) { - this._delta = delta; - } - - muteSoundLibraries(): void { - this._libraryManager.getMutableLibraries().forEach((lib) => lib.library.mute()); - } -} 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 deleted file mode 100644 index 1081686d..00000000 --- a/packages/core/src/common/context/contexts/executions/clear.editable-context.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ClearContext } from "@nanoforge-dev/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 deleted file mode 100644 index e9b5b3de..00000000 --- a/packages/core/src/common/context/contexts/executions/execution.editable-context.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ExecutionContext } from "@nanoforge-dev/common"; - -export class EditableExecutionContext extends ExecutionContext {} 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 deleted file mode 100644 index 7ce44e10..00000000 --- a/packages/core/src/common/context/contexts/executions/init.editable-context.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { InitContext } from "@nanoforge-dev/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 deleted file mode 100644 index 48f942e8..00000000 --- a/packages/core/src/common/context/contexts/library.editable-context.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { LibraryContext, type LibraryStatusEnum } from "@nanoforge-dev/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 deleted file mode 100644 index 6e17b321..00000000 --- a/packages/core/src/common/library/manager/library.manager.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { - ASSET_MANAGER_LIBRARY, - COMPONENT_SYSTEM_LIBRARY, - DefaultLibrariesEnum, - GRAPHICS_LIBRARY, - type IAssetManagerLibrary, - type IComponentSystemLibrary, - type IGraphicsLibrary, - type IInputLibrary, - type ILibrary, - type IMusicLibrary, - type IMutableLibrary, - INPUT_LIBRARY, - type INetworkLibrary, - type IRunnerLibrary, - type ISoundLibrary, - type LibraryHandle, - LibraryManager, - MUSIC_LIBRARY, - NETWORK_LIBRARY, - SOUND_LIBRARY, -} from "@nanoforge-dev/common"; - -import { EditableLibraryContext } from "../../context/contexts/library.editable-context"; -import { Relationship } from "../relationship-functions"; - -const hasMethod = (obj: any, method: string) => { - return typeof obj[method] === "function"; -}; - -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 setSound(library: ISoundLibrary): void { - this._set(DefaultLibrariesEnum.SOUND, SOUND_LIBRARY, library, new EditableLibraryContext()); - } - - public setMusic(library: IMusicLibrary): void { - this._set(DefaultLibrariesEnum.MUSIC, MUSIC_LIBRARY, library, new EditableLibraryContext()); - } - - public getLibraries(): LibraryHandle[] { - return this._libraries; - } - - public getInitLibraries(): LibraryHandle[] { - return Relationship.getLibrariesByDependencies(this._libraries); - } - - public getExecutionLibraries(): LibraryHandle[] { - return Relationship.getLibrariesByRun(this._getRunnerLibraries()); - } - - public getClearLibraries(): LibraryHandle[] { - return Relationship.getLibrariesByDependencies(this._libraries, true); - } - - public getMutableLibraries(): LibraryHandle[] { - return this._libraries.filter( - (handle) => handle && hasMethod(handle.library, "mute"), - ) as LibraryHandle[]; - } - - private _getRunnerLibraries(): LibraryHandle[] { - return this._libraries.filter( - (handle) => handle && hasMethod(handle.library, "__run"), - ) as LibraryHandle[]; - } -} diff --git a/packages/core/src/common/library/relationship-functions.ts b/packages/core/src/common/library/relationship-functions.ts deleted file mode 100644 index d9ff0f2b..00000000 --- a/packages/core/src/common/library/relationship-functions.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { type ILibrary, type LibraryHandle } from "@nanoforge-dev/common"; - -class RelationshipStatic { - getLibrariesByDependencies(libraries: LibraryHandle[], reverse: boolean = false) { - let response: LibraryHandle[] = []; - for (const library of libraries) { - if (!library) continue; - response = this._pushLibraryWithDependencies(library, response, [], libraries); - } - - if (reverse) return response.reverse(); - return response; - } - - getLibrariesByRun(libraries: LibraryHandle[]) { - let response: LibraryHandle[] = []; - const dependencies = new Map>( - libraries.map((library) => [library.symbol, new Set()]), - ); - - for (const handle of libraries) { - const key = handle.symbol; - - for (const before of handle.library.__relationship.runBefore) { - this._pushToDependencies(key, before, dependencies); - } - for (const after of handle.library.__relationship.runAfter) { - this._pushToDependencies(after, key, dependencies); - } - } - - for (const library of libraries) { - response = this._pushLibraryWithDependenciesRun( - library, - dependencies, - response, - [], - libraries, - ); - } - return response; - } - - private _pushToDependencies( - key: symbol, - value: symbol, - dependencies: Map>, - ): void { - let curr = dependencies.get(key); - if (!curr) curr = new Set(); - curr.add(value); - dependencies.set(key, curr); - } - - private _pushLibraryWithDependenciesRun( - handle: LibraryHandle, - dependencies: Map>, - response: LibraryHandle[], - cache: symbol[], - libraries: LibraryHandle[], - ): LibraryHandle[] { - const key = handle.symbol; - if (this._symbolIsInList(key, response)) return response; - - if (cache.includes(key)) throw new Error("Circular dependencies !"); - - cache.push(key); - - const deps = dependencies.get(key); - if (!deps) throw new Error("Dependencies not found"); - - for (const dep of deps) { - if (this._symbolIsInList(dep, response)) continue; - - const depHandle = libraries.find((lib) => lib?.symbol === dep) as LibraryHandle; - if (!depHandle) throw new Error(`Cannot find library ${dep.toString()}`); - - response = this._pushLibraryWithDependenciesRun( - depHandle, - dependencies, - response, - cache, - libraries, - ); - } - cache.pop(); - - response.push(handle); - return response; - } - - private _pushLibraryWithDependencies( - handle: LibraryHandle, - response: LibraryHandle[], - cache: symbol[], - libraries: LibraryHandle[], - ): LibraryHandle[] { - if (this._symbolIsInList(handle.symbol, response)) return response; - - if (cache.includes(handle.symbol)) throw new Error("Circular dependencies !"); - - cache.push(handle.symbol); - for (const dep of handle.library.__relationship.dependencies) { - if (this._symbolIsInList(dep, response)) continue; - - const depHandle = libraries.find((lib) => lib?.symbol === dep) as LibraryHandle; - if (!depHandle) throw new Error(`Cannot find library ${dep.toString()}`); - - response = this._pushLibraryWithDependencies(depHandle, response, cache, libraries); - } - cache.pop(); - - response.push(handle); - return response; - } - - private _symbolIsInList(sym: symbol, libraries: LibraryHandle[]): boolean { - return libraries.some((lib) => lib.symbol === sym); - } -} - -export const Relationship = new RelationshipStatic(); diff --git a/packages/core/src/config/config-registry.ts b/packages/core/src/config/config-registry.ts deleted file mode 100644 index 946ed1dc..00000000 --- a/packages/core/src/config/config-registry.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { plainToInstance } from "class-transformer"; -import { validate } from "class-validator"; - -export class ConfigRegistry { - private readonly _env: Record; - - constructor(env: Record) { - this._env = env; - } - - async registerConfig(config: new () => T): Promise { - const data = plainToInstance(config, this._env, { excludeExtraneousValues: true }); - const errors = await validate(data); - if (errors.length > 0) { - throw new Error(errors.toString()); - } - return data; - } -} diff --git a/packages/core/src/core/core.ts b/packages/core/src/core/core.ts deleted file mode 100644 index 1badedcf..00000000 --- a/packages/core/src/core/core.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - ClearContext, - ClientLibraryManager, - Context, - type IRunOptions, - type IRunnerLibrary, - InitContext, - type LibraryHandle, - LibraryStatusEnum, - NfNotInitializedException, -} from "@nanoforge-dev/common"; - -import { type ApplicationConfig } from "../application/application-config"; -import type { IApplicationOptions } from "../application/application-options.type"; -import { type EditableApplicationContext } from "../common/context/contexts/application.editable-context"; -import { EditableExecutionContext } from "../common/context/contexts/executions/execution.editable-context"; -import { type EditableLibraryContext } from "../common/context/contexts/library.editable-context"; -import { ConfigRegistry } from "../config/config-registry"; - -export class Core { - private readonly config: ApplicationConfig; - private readonly context: EditableApplicationContext; - private options?: IApplicationOptions; - private _configRegistry?: ConfigRegistry; - - constructor(config: ApplicationConfig, context: EditableApplicationContext) { - this.config = config; - this.context = context; - } - - public async init(options: IRunOptions, appOptions: IApplicationOptions): Promise { - this.options = appOptions; - this._configRegistry = new ConfigRegistry(options.env); - await this.runInit(this.getInitContext(options)); - } - - public async run(): Promise { - if (!this.options) throw new NfNotInitializedException("Core"); - - const context = this.getExecutionContext(); - const clientContext = this.getClientContext(); - const libraries = this.config.libraryManager.getExecutionLibraries(); - - const runner = async (delta: number) => { - this.context.setDelta(delta); - await this.runExecute(clientContext, libraries); - }; - - const tickLengthMs = 1000 / this.options.tickRate; - let previousTick = Date.now(); - - const render = async () => { - if (!context.application.isRunning) { - await this.runClear(this.getClearContext()); - return; - } - const tickStart = Date.now(); - await runner(tickStart - previousTick); - previousTick = tickStart; - setTimeout(render, tickLengthMs + tickStart - Date.now()); - }; - - context.application.setIsRunning(true); - setTimeout(render); - } - - private getInitContext(options: IRunOptions): InitContext { - if (!this._configRegistry) throw new NfNotInitializedException("Core"); - - return new InitContext(this.context, this.config.libraryManager, this._configRegistry, options); - } - - private getExecutionContext(): EditableExecutionContext { - return new EditableExecutionContext(this.context, this.config.libraryManager); - } - - private getClearContext(): ClearContext { - return new ClearContext(this.context, this.config.libraryManager); - } - - private getClientContext(): Context { - return new Context(this.context, new ClientLibraryManager(this.config.libraryManager)); - } - - private async runInit(context: InitContext): Promise { - for (const handle of this.config.libraryManager.getInitLibraries()) { - await handle.library.__init(context); - (handle.context as EditableLibraryContext).setStatus(LibraryStatusEnum.LOADED); - } - } - - private async runExecute(context: Context, libraries: LibraryHandle[]) { - for (const handle of libraries) { - await handle.library.__run(context); - } - } - - private async runClear(context: ClearContext) { - for (const handle of this.config.libraryManager.getClearLibraries()) { - await handle.library.__clear(context); - (handle.context as EditableLibraryContext).setStatus(LibraryStatusEnum.CLEAR); - } - } -} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 4273d62e..c958ad63 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,4 @@ -export * from "./application/nanoforge-factory"; - +export type { ApplicationOptions } from "./application/application-options.type"; export type { NanoforgeClient } from "./application/nanoforge-client"; +export { NanoforgeFactory } from "./application/nanoforge-factory"; export type { NanoforgeServer } from "./application/nanoforge-server"; diff --git a/packages/core/src/internal/internal-app-state.ts b/packages/core/src/internal/internal-app-state.ts new file mode 100644 index 00000000..d5fb3058 --- /dev/null +++ b/packages/core/src/internal/internal-app-state.ts @@ -0,0 +1,68 @@ +import type { AppContext } from "@nanoforge-dev/common"; + +/** + * The only place `app`'s state can be mutated. + * + * @remarks + * Never exported from this package. `asAppContext()` returns a view backed + * by live getters (not a snapshot), so `ctx.app.isRunning`/`.delta` reflect + * current state across ticks without `Context` being rebuilt every frame. + */ +export class InternalAppState { + private readonly _tickRate: number; + private _isRunning = false; + private _isPaused = false; + private _delta = 0; + + constructor(tickRate: number) { + this._tickRate = tickRate; + } + + get isRunning(): boolean { + return this._isRunning; + } + + get isPaused(): boolean { + return this._isPaused; + } + + setIsRunning(value: boolean): void { + this._isRunning = value; + } + + setIsPaused(value: boolean): void { + this._isPaused = value; + } + + setDelta(value: number): void { + this._delta = value; + } + + asAppContext(): AppContext { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const state = this; + return { + get isRunning() { + return state._isRunning; + }, + get isPaused() { + return state._isPaused; + }, + get delta() { + return state._delta; + }, + get tickRate() { + return state._tickRate; + }, + requestStop: () => { + state.setIsRunning(false); + }, + requestPause: () => { + state.setIsPaused(true); + }, + requestResume: () => { + state.setIsPaused(false); + }, + }; + } +} diff --git a/packages/core/src/internal/internal-vars-state.ts b/packages/core/src/internal/internal-vars-state.ts new file mode 100644 index 00000000..54682a4c --- /dev/null +++ b/packages/core/src/internal/internal-vars-state.ts @@ -0,0 +1,25 @@ +import type { VarsContext } from "@nanoforge-dev/common"; + +/** + * The only place `vars`' storage lives. + * + * @remarks + * Unlike `InternalAppState`, mutation (`set`) is intentionally public on + * the returned `VarsContext` — `vars` is the dev-editable half of `Context`. + */ +export class InternalVarsState { + private readonly map: Map; + + constructor(initial?: Record) { + this.map = new Map(Object.entries(initial ?? {})); + } + + asVarsContext(): VarsContext { + return { + get: (key: string) => this.map.get(key), + set: (key: string, value: unknown) => { + this.map.set(key, value); + }, + }; + } +} diff --git a/packages/core/src/library-registry/library-registry.ts b/packages/core/src/library-registry/library-registry.ts new file mode 100644 index 00000000..1be282a0 --- /dev/null +++ b/packages/core/src/library-registry/library-registry.ts @@ -0,0 +1,59 @@ +import { + type AppContext, + type Context, + type Library, + NfDuplicateLibraryException, + type VarsContext, +} from "@nanoforge-dev/common"; + +import { orderByDependencies, orderByRunSequence } from "./ordering"; + +const RESERVED_KEYS = new Set(["app", "vars", "assets"]); + +/** + * Owns every registered library, enforces key uniqueness, and assembles + * `Context` from their `expose()` results. + * + * @remarks + * Not exported from `@nanoforge-dev/core` — purely internal to + * `NanoforgeApplication`. + */ +export class LibraryRegistry { + private readonly libraries = new Map(); + + /** + * Registers the mandatory built-in asset library, bypassing the + * reserved-key check that applies to `.use()`. + */ + registerBuiltin(library: Library): void { + this.libraries.set(library.key, library); + } + + register(library: Library): void { + if (RESERVED_KEYS.has(library.key) || this.libraries.has(library.key)) { + throw new NfDuplicateLibraryException(library.key); + } + this.libraries.set(library.key, library); + } + + getAll(): Library[] { + return [...this.libraries.values()]; + } + + getOrderedForInit(): Library[] { + return orderByDependencies(this.getAll()); + } + + getOrderedForRun(): Library[] { + return orderByRunSequence(this.getAll()); + } + + buildContext(app: AppContext, vars: VarsContext): Context { + const ctx: Record = { app, vars }; + for (const library of this.getAll()) { + const exposed = library.expose(); + if (exposed !== undefined) ctx[library.key] = exposed; + } + return ctx as Context; + } +} diff --git a/packages/core/src/library-registry/ordering.ts b/packages/core/src/library-registry/ordering.ts new file mode 100644 index 00000000..f077f660 --- /dev/null +++ b/packages/core/src/library-registry/ordering.ts @@ -0,0 +1,55 @@ +import type { Library } from "@nanoforge-dev/common"; + +const topologicalOrder = ( + libraries: Library[], + getDependencyKeys: (lib: Library) => string[], +): Library[] => { + const byKey = new Map(libraries.map((lib) => [lib.key, lib])); + const ordered: Library[] = []; + const visited = new Set(); + const visiting: string[] = []; + + const visit = (lib: Library): void => { + if (visited.has(lib.key)) return; + if (visiting.includes(lib.key)) throw new Error("Circular dependencies!"); + + visiting.push(lib.key); + for (const depKey of getDependencyKeys(lib)) { + const dep = byKey.get(depKey); + if (!dep) throw new Error(`Cannot find library "${depKey}"`); + visit(dep); + } + visiting.pop(); + + visited.add(lib.key); + ordered.push(lib); + }; + + for (const lib of libraries) visit(lib); + return ordered; +}; + +/** Orders libraries so each one's `dependencies` come before it. */ +export const orderByDependencies = (libraries: Library[]): Library[] => + topologicalOrder(libraries, (lib) => lib.relationships.dependencies); + +/** + * Orders libraries for the tick loop: each library's `runBefore` entries + * come before it, and its `runAfter` entries come after it. + */ +export const orderByRunSequence = (libraries: Library[]): Library[] => { + const runDependencies = new Map>( + libraries.map((lib) => [lib.key, new Set()]), + ); + + for (const library of libraries) { + for (const before of library.relationships.runBefore) { + runDependencies.get(library.key)?.add(before); + } + for (const after of library.relationships.runAfter) { + runDependencies.get(after)?.add(library.key); + } + } + + return topologicalOrder(libraries, (lib) => [...(runDependencies.get(lib.key) ?? [])]); +}; diff --git a/packages/core/test/config-registry.spec.ts b/packages/core/test/config-registry.spec.ts deleted file mode 100644 index 0a1e2844..00000000 --- a/packages/core/test/config-registry.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Expose } from "class-transformer"; -import { IsString } from "class-validator"; -import { describe, expect, it } from "vitest"; - -import { ConfigRegistry } from "../src/config/config-registry"; - -class ValidConfig { - @Expose() - @IsString() - name!: string; -} - -class OptionalConfig { - @Expose() - @IsString() - name!: string; - - @Expose() - host?: string; -} - -describe("ConfigRegistry", () => { - describe("registerConfig", () => { - it("should return a transformed config instance when env is valid", async () => { - const registry = new ConfigRegistry({ name: "hello" }); - const config = await registry.registerConfig(ValidConfig); - expect(config).toBeInstanceOf(ValidConfig); - expect(config.name).toBe("hello"); - }); - - it("should exclude values not decorated with @Expose", async () => { - const registry = new ConfigRegistry({ name: "hello", extra: "ignored" }); - const config = await registry.registerConfig(ValidConfig); - expect((config as any)["extra"]).toBeUndefined(); - }); - - it("should throw when a required field is missing", async () => { - const registry = new ConfigRegistry({}); - await expect(registry.registerConfig(ValidConfig)).rejects.toThrow(); - }); - - it("should throw when a field has the wrong type", async () => { - const registry = new ConfigRegistry({ name: 42 }); - await expect(registry.registerConfig(ValidConfig)).rejects.toThrow(); - }); - - it("should map multiple env fields correctly", async () => { - const registry = new ConfigRegistry({ name: "world", host: "localhost" }); - const config = await registry.registerConfig(OptionalConfig); - expect(config.name).toBe("world"); - expect(config.host).toBe("localhost"); - }); - }); -}); diff --git a/packages/core/test/editable-library-manager.spec.ts b/packages/core/test/editable-library-manager.spec.ts deleted file mode 100644 index 0e808baa..00000000 --- a/packages/core/test/editable-library-manager.spec.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { COMPONENT_SYSTEM_LIBRARY, type ILibrary, LibraryStatusEnum } from "@nanoforge-dev/common"; -import { beforeEach, describe, expect, it } from "vitest"; - -import { Library } from "../../common/src/library/libraries/library"; -import { EditableLibraryManager } from "../src/common/library/manager/library.manager"; - -class StubLibrary extends Library { - private readonly _name: string; - - constructor(name: string, options?: ConstructorParameters[0]) { - super(options); - this._name = name; - } - - get __name(): string { - return this._name; - } -} - -class StubRunnerLibrary extends StubLibrary { - async __run(): Promise {} -} - -class StubMutableLibrary extends StubLibrary { - mute(): void {} -} - -describe("EditableLibraryManager", () => { - let manager: EditableLibraryManager; - - beforeEach(() => { - manager = new EditableLibraryManager(); - }); - - describe("typed setters and getters", () => { - it("should store and retrieve a component system library", () => { - const lib = new StubLibrary("ComponentSystem"); - manager.setComponentSystem(lib as any); - expect(manager.getComponentSystem().library).toBe(lib); - }); - - it("should store and retrieve a graphics library", () => { - const lib = new StubLibrary("Graphics"); - manager.setGraphics(lib as any); - expect(manager.getGraphics().library).toBe(lib); - }); - - it("should store and retrieve an asset manager library", () => { - const lib = new StubLibrary("AssetManager"); - manager.setAssetManager(lib as any); - expect(manager.getAssetManager().library).toBe(lib); - }); - - it("should store and retrieve a network library", () => { - const lib = new StubLibrary("Network"); - manager.setNetwork(lib as any); - expect(manager.getNetwork().library).toBe(lib); - }); - - it("should store and retrieve an input library", () => { - const lib = new StubLibrary("Input"); - manager.setInput(lib as any); - expect(manager.getInput().library).toBe(lib); - }); - - it("should store and retrieve a sound library", () => { - const lib = new StubLibrary("Sound"); - manager.setSound(lib as any); - expect(manager.getSound().library).toBe(lib); - }); - - it("should store and retrieve a music library", () => { - const lib = new StubLibrary("Music"); - manager.setMusic(lib as any); - expect(manager.getMusic().library).toBe(lib); - }); - - it("should throw when getting a typed library that was not set", () => { - expect(() => manager.getComponentSystem()).toThrow(); - }); - }); - - describe("set and get (custom symbol)", () => { - it("should store and retrieve a library by Symbol.for key", () => { - const sym = Symbol.for("customLib"); - const lib = new StubLibrary("Custom"); - - manager.setAssetManager(new StubLibrary("Asset") as any); - manager.set(sym, lib as unknown as ILibrary); - - expect(manager.get(sym).library).toBe(lib); - }); - }); - - describe("getLibraries", () => { - it("should return the list of all set libraries", () => { - const lib = new StubLibrary("ComponentSystem"); - manager.setComponentSystem(lib as any); - const libs = manager.getLibraries().filter(Boolean); - expect(libs.some((h) => h.library === (lib as unknown as ILibrary))).toBe(true); - }); - }); - - describe("getInitLibraries", () => { - it("should return libraries in dependency order", () => { - const libA = new StubLibrary("A", { dependencies: [COMPONENT_SYSTEM_LIBRARY] }); - const libB = new StubLibrary("B"); - - manager.setComponentSystem(libB as any); - manager.setGraphics(libA as any); - - const order = manager.getInitLibraries().map((h) => h.library.__name); - const idxB = order.indexOf("B"); - const idxA = order.indexOf("A"); - - expect(idxB).toBeLessThan(idxA); - }); - - it("should return all set libraries", () => { - manager.setAssetManager(new StubLibrary("Asset") as any); - manager.setGraphics(new StubLibrary("Graphics") as any); - - expect(manager.getInitLibraries().length).toBe(2); - }); - }); - - describe("getClearLibraries", () => { - it("should return libraries in reverse dependency order", () => { - const libA = new StubLibrary("A", { dependencies: [COMPONENT_SYSTEM_LIBRARY] }); - const libB = new StubLibrary("B"); - - manager.setComponentSystem(libB as any); - manager.setGraphics(libA as any); - - const order = manager.getClearLibraries().map((h) => h.library.__name); - const idxA = order.indexOf("A"); - const idxB = order.indexOf("B"); - - expect(idxA).toBeLessThan(idxB); - }); - }); - - describe("getExecutionLibraries", () => { - it("should only return libraries that implement __run", () => { - manager.setComponentSystem(new StubLibrary("NotARunner") as any); - manager.setGraphics(new StubRunnerLibrary("Runner") as any); - - const runners = manager.getExecutionLibraries(); - expect(runners.every((h) => typeof (h.library as any).__run === "function")).toBe(true); - expect(runners.some((h) => h.library.__name === "Runner")).toBe(true); - expect(runners.some((h) => h.library.__name === "NotARunner")).toBe(false); - }); - - it("should return empty when no runner libraries are set", () => { - manager.setComponentSystem(new StubLibrary("Static") as any); - expect(manager.getExecutionLibraries()).toHaveLength(0); - }); - }); - - describe("getMutableLibraries", () => { - it("should only return libraries that implement mute", () => { - manager.setSound(new StubMutableLibrary("MutableSound") as any); - manager.setGraphics(new StubLibrary("NonMutableGraphics") as any); - - const mutable = manager.getMutableLibraries(); - expect(mutable.some((h) => h.library.__name === "MutableSound")).toBe(true); - expect(mutable.some((h) => h.library.__name === "NonMutableGraphics")).toBe(false); - }); - - it("should return empty when no mutable libraries are set", () => { - manager.setGraphics(new StubLibrary("Graphics") as any); - expect(manager.getMutableLibraries()).toHaveLength(0); - }); - }); - - describe("library context status", () => { - it("should start with UNLOADED status", () => { - manager.setComponentSystem(new StubLibrary("Comp") as any); - expect(manager.getComponentSystem().context.status).toBe(LibraryStatusEnum.UNLOADED); - }); - }); -}); diff --git a/packages/core/test/internal-app-state.spec.ts b/packages/core/test/internal-app-state.spec.ts new file mode 100644 index 00000000..54e6635f --- /dev/null +++ b/packages/core/test/internal-app-state.spec.ts @@ -0,0 +1,60 @@ +import { describe, expect, it } from "vitest"; + +import { InternalAppState } from "../src/internal/internal-app-state"; + +describe("InternalAppState", () => { + it("reflects the configured tickRate", () => { + const state = new InternalAppState(30); + expect(state.asAppContext().tickRate).toBe(30); + }); + + it("starts not running, not paused, with zero delta", () => { + const state = new InternalAppState(60); + const ctx = state.asAppContext(); + expect(ctx.isRunning).toBe(false); + expect(ctx.isPaused).toBe(false); + expect(ctx.delta).toBe(0); + }); + + it("the returned view reflects live state, not a snapshot", () => { + const state = new InternalAppState(60); + const ctx = state.asAppContext(); + + state.setIsRunning(true); + state.setDelta(16); + + expect(ctx.isRunning).toBe(true); + expect(ctx.delta).toBe(16); + }); + + it("requestStop() stops the run state", () => { + const state = new InternalAppState(60); + state.setIsRunning(true); + const ctx = state.asAppContext(); + + ctx.requestStop(); + + expect(state.isRunning).toBe(false); + expect(ctx.isRunning).toBe(false); + }); + + it("requestPause()/requestResume() toggle isPaused", () => { + const state = new InternalAppState(60); + const ctx = state.asAppContext(); + + ctx.requestPause(); + expect(state.isPaused).toBe(true); + expect(ctx.isPaused).toBe(true); + + ctx.requestResume(); + expect(state.isPaused).toBe(false); + expect(ctx.isPaused).toBe(false); + }); + + it("has no setter reachable on the returned view", () => { + const ctx = new InternalAppState(60).asAppContext(); + expect("setIsRunning" in ctx).toBe(false); + expect("setIsPaused" in ctx).toBe(false); + expect("setDelta" in ctx).toBe(false); + }); +}); diff --git a/packages/core/test/internal-vars-state.spec.ts b/packages/core/test/internal-vars-state.spec.ts new file mode 100644 index 00000000..859a95f4 --- /dev/null +++ b/packages/core/test/internal-vars-state.spec.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from "vitest"; + +import { InternalVarsState } from "../src/internal/internal-vars-state"; + +describe("InternalVarsState", () => { + it("returns undefined for an unset key", () => { + const vars = new InternalVarsState().asVarsContext(); + expect(vars.get("score")).toBeUndefined(); + }); + + it("seeds from the given initial values", () => { + const vars = new InternalVarsState({ score: 0 }).asVarsContext(); + expect(vars.get("score")).toBe(0); + }); + + it("set() is reflected by later get() calls", () => { + const vars = new InternalVarsState().asVarsContext(); + vars.set("score", 10); + expect(vars.get("score")).toBe(10); + }); +}); diff --git a/packages/core/test/nanoforge-application.spec.ts b/packages/core/test/nanoforge-application.spec.ts new file mode 100644 index 00000000..769e450b --- /dev/null +++ b/packages/core/test/nanoforge-application.spec.ts @@ -0,0 +1,249 @@ +import { + type Context, + type InitContext, + Library, + NfDuplicateLibraryException, + NfNotInitializedException, +} from "@nanoforge-dev/common"; +import { afterEach, describe, expect, it, vi } from "vitest"; + +import { NanoforgeServer } from "../src/application/nanoforge-server"; + +class RecordingLibrary extends Library { + public capturedContext?: Context; + public runCount = 0; + public eventsCount = 0; + public clearCount = 0; + + constructor( + public readonly key: string, + private readonly initLog: string[], + options?: ConstructorParameters[0], + ) { + super(options); + } + + override async __init(_ctx: InitContext): Promise { + this.initLog.push(this.key); + } + + override async __events(ctx: Context): Promise { + this.eventsCount++; + this.capturedContext = ctx; + } + + override async __run(ctx: Context): Promise { + this.runCount++; + this.capturedContext = ctx; + } + + override async __clear(_ctx: Context): Promise { + this.clearCount++; + } + + override expose(): { key: string } { + return { key: this.key }; + } +} + +class StoppingLibrary extends Library { + readonly key = "stopper"; + public runCount = 0; + public clearCount = 0; + + override async __run(ctx: Context): Promise { + this.runCount++; + ctx.app.requestStop(); + } + + override async __clear(): Promise { + this.clearCount++; + } +} + +const makeRunOptions = () => ({ files: new Map(), env: {} }); + +describe("NanoforgeApplication", () => { + afterEach(() => { + vi.useRealTimers(); + }); + + describe("use", () => { + it("throws NfDuplicateLibraryException on a duplicate key", async () => { + const server = new NanoforgeServer(); + server.use(new RecordingLibrary("a", [])); + expect(() => server.use(new RecordingLibrary("a", []))).toThrow(NfDuplicateLibraryException); + }); + + it("throws NfDuplicateLibraryException on a reserved key", () => { + const server = new NanoforgeServer(); + expect(() => server.use(new RecordingLibrary("assets", []))).toThrow( + NfDuplicateLibraryException, + ); + expect(() => server.use(new RecordingLibrary("app", []))).toThrow( + NfDuplicateLibraryException, + ); + expect(() => server.use(new RecordingLibrary("vars", []))).toThrow( + NfDuplicateLibraryException, + ); + }); + + it("throws after init() has been called", async () => { + const server = new NanoforgeServer(); + await server.init(makeRunOptions()); + expect(() => server.use(new RecordingLibrary("late", []))).toThrow(); + }); + }); + + describe("init", () => { + it("initializes libraries in dependency order", async () => { + const log: string[] = []; + const server = new NanoforgeServer(); + const a = new RecordingLibrary("a", log, { dependencies: ["b"] }); + const b = new RecordingLibrary("b", log); + server.use(a); + server.use(b); + + await server.init(makeRunOptions()); + + expect(log).toEqual(["b", "a"]); + }); + + it("makes ctx.assets available without it being explicitly registered", async () => { + const server = new NanoforgeServer(); + const probe = new RecordingLibrary("probe", []); + server.use(probe); + await server.init(makeRunOptions()); + + vi.useFakeTimers(); + await server.run(); + await vi.advanceTimersByTimeAsync(50); + + expect(probe.capturedContext?.assets).toBeDefined(); + expect(typeof probe.capturedContext?.assets.getAsset).toBe("function"); + }); + + it("assigns a library's expose() result to ctx[key]", async () => { + const server = new NanoforgeServer(); + const probe = new RecordingLibrary("probe", []); + server.use(probe); + await server.init(makeRunOptions()); + + vi.useFakeTimers(); + await server.run(); + await vi.advanceTimersByTimeAsync(50); + + expect((probe.capturedContext as any).probe).toEqual({ key: "probe" }); + }); + }); + + describe("run", () => { + it("throws NfNotInitializedException if called before init()", async () => { + const server = new NanoforgeServer(); + await expect(server.run()).rejects.toThrow(NfNotInitializedException); + }); + + it("calls __run each tick and stops after requestStop()", async () => { + vi.useFakeTimers(); + + const server = new NanoforgeServer({ tickRate: 1000 }); + const stopper = new StoppingLibrary(); + server.use(stopper); + await server.init(makeRunOptions()); + + await server.run(); + await vi.advanceTimersByTimeAsync(10); // tick 1: __run fires, requests stop + await vi.advanceTimersByTimeAsync(10); // tick 2: sees isRunning === false, runs __clear + + expect(stopper.runCount).toBe(1); + expect(stopper.clearCount).toBe(1); + }); + + it("skips __run on every library while paused, then resumes", async () => { + vi.useFakeTimers(); + + const server = new NanoforgeServer({ tickRate: 60 }); + const probe = new RecordingLibrary("probe", []); + server.use(probe); + await server.init(makeRunOptions()); + + await server.run(); + await vi.advanceTimersByTimeAsync(1); // let the first tick fire + const runsBeforePause = probe.runCount; + expect(runsBeforePause).toBeGreaterThan(0); + + probe.capturedContext!.app.requestPause(); + await vi.advanceTimersByTimeAsync(200); // many tick intervals while paused + expect(probe.runCount).toBe(runsBeforePause); + expect(probe.capturedContext!.app.isPaused).toBe(true); + + probe.capturedContext!.app.requestResume(); + await vi.advanceTimersByTimeAsync(50); // at least one more tick after resume + expect(probe.runCount).toBeGreaterThan(runsBeforePause); + }); + + it("keeps calling __events every tick while paused, unlike __run", async () => { + vi.useFakeTimers(); + + const server = new NanoforgeServer({ tickRate: 60 }); + const probe = new RecordingLibrary("probe", []); + server.use(probe); + await server.init(makeRunOptions()); + + await server.run(); + await vi.advanceTimersByTimeAsync(1); // let the first tick fire + const runsBeforePause = probe.runCount; + const eventsBeforePause = probe.eventsCount; + expect(runsBeforePause).toBeGreaterThan(0); + expect(eventsBeforePause).toBeGreaterThan(0); + + probe.capturedContext!.app.requestPause(); + await vi.advanceTimersByTimeAsync(200); // many tick intervals while paused + + expect(probe.runCount).toBe(runsBeforePause); // __run stayed skipped + expect(probe.eventsCount).toBeGreaterThan(eventsBeforePause); // __events kept running + + probe.capturedContext!.app.requestResume(); + await vi.advanceTimersByTimeAsync(50); + expect(probe.runCount).toBeGreaterThan(runsBeforePause); + }); + + it("resumes on the same tick an event handler calls requestResume(), since __events runs before the pause check", async () => { + vi.useFakeTimers(); + + class EditorStandIn extends Library { + readonly key = "editor"; + private _resumeQueued = false; + + queueResume(): void { + this._resumeQueued = true; + } + + override async __events(ctx: Context): Promise { + if (this._resumeQueued) { + ctx.app.requestResume(); + this._resumeQueued = false; + } + } + } + + const server = new NanoforgeServer({ tickRate: 60 }); + const editor = new EditorStandIn(); + const probe = new RecordingLibrary("probe", []); + server.use(editor); + server.use(probe); + await server.init(makeRunOptions()); + + await server.run(); + await vi.advanceTimersByTimeAsync(1); + probe.capturedContext!.app.requestPause(); + await vi.advanceTimersByTimeAsync(200); + const runsWhilePaused = probe.runCount; + + editor.queueResume(); + await vi.advanceTimersByTimeAsync(50); // next tick: __events drains the resume, __run fires too + + expect(probe.runCount).toBeGreaterThan(runsWhilePaused); + }); + }); +}); diff --git a/packages/core/test/nanoforge-factory.spec.ts b/packages/core/test/nanoforge-factory.spec.ts new file mode 100644 index 00000000..e6b203cd --- /dev/null +++ b/packages/core/test/nanoforge-factory.spec.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from "vitest"; + +import { NanoforgeFactory } from "../src/application/nanoforge-factory"; + +describe("NanoforgeFactory", () => { + it("creates a client that can be initialized", async () => { + const client = NanoforgeFactory.createClient(); + await expect( + client.init({ files: new Map(), env: {}, container: {} as unknown as HTMLDivElement }), + ).resolves.toBeUndefined(); + }); + + it("creates a server that can be initialized", async () => { + const server = NanoforgeFactory.createServer({ tickRate: 30 }); + await expect(server.init({ files: new Map(), env: {} })).resolves.toBeUndefined(); + }); +}); diff --git a/packages/core/test/ordering.spec.ts b/packages/core/test/ordering.spec.ts new file mode 100644 index 00000000..06309952 --- /dev/null +++ b/packages/core/test/ordering.spec.ts @@ -0,0 +1,79 @@ +import { Library } from "@nanoforge-dev/common"; +import { describe, expect, it } from "vitest"; + +import { orderByDependencies, orderByRunSequence } from "../src/library-registry/ordering"; + +class StubLibrary extends Library { + constructor( + public readonly key: string, + options?: ConstructorParameters[0], + ) { + super(options); + } +} + +describe("orderByDependencies", () => { + it("returns libraries in the same order when no dependencies are declared", () => { + const a = new StubLibrary("A"); + const b = new StubLibrary("B"); + expect(orderByDependencies([a, b]).map((l) => l.key)).toEqual(["A", "B"]); + }); + + it("puts a dependency before the library that depends on it", () => { + const b = new StubLibrary("B"); + const a = new StubLibrary("A", { dependencies: ["B"] }); + const result = orderByDependencies([a, b]).map((l) => l.key); + expect(result.indexOf("B")).toBeLessThan(result.indexOf("A")); + }); + + it("does not duplicate a shared dependency", () => { + const dep = new StubLibrary("Dep"); + const a = new StubLibrary("A", { dependencies: ["Dep"] }); + const b = new StubLibrary("B", { dependencies: ["Dep"] }); + const result = orderByDependencies([a, b, dep]).map((l) => l.key); + expect(result.filter((k) => k === "Dep")).toHaveLength(1); + }); + + it("throws on circular dependencies", () => { + const a = new StubLibrary("A", { dependencies: ["B"] }); + const b = new StubLibrary("B", { dependencies: ["A"] }); + expect(() => orderByDependencies([a, b])).toThrow(/[Cc]ircular/); + }); + + it("throws when a dependency key doesn't exist", () => { + const a = new StubLibrary("A", { dependencies: ["Missing"] }); + expect(() => orderByDependencies([a])).toThrow(/Missing/); + }); +}); + +describe("orderByRunSequence", () => { + it("returns all libraries when no ordering is specified", () => { + const a = new StubLibrary("A"); + const b = new StubLibrary("B"); + expect(orderByRunSequence([a, b])).toHaveLength(2); + }); + + it("places a library's runBefore entry before it", () => { + const a = new StubLibrary("A", { runBefore: ["B"] }); + const b = new StubLibrary("B"); + const result = orderByRunSequence([a, b]).map((l) => l.key); + expect(result.indexOf("B")).toBeLessThan(result.indexOf("A")); + }); + + it("places a library's runAfter entry after it", () => { + const a = new StubLibrary("A"); + const b = new StubLibrary("B", { runAfter: ["A"] }); + const result = orderByRunSequence([a, b]).map((l) => l.key); + expect(result.indexOf("B")).toBeLessThan(result.indexOf("A")); + }); + + it("throws on circular run ordering", () => { + const a = new StubLibrary("A", { runBefore: ["B"] }); + const b = new StubLibrary("B", { runBefore: ["A"] }); + expect(() => orderByRunSequence([a, b])).toThrow(/[Cc]ircular/); + }); + + it("returns an empty array for empty input", () => { + expect(orderByRunSequence([])).toHaveLength(0); + }); +}); diff --git a/packages/core/test/relationship.spec.ts b/packages/core/test/relationship.spec.ts deleted file mode 100644 index 776fa493..00000000 --- a/packages/core/test/relationship.spec.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { type ILibrary, LibraryContext, LibraryHandle } from "@nanoforge-dev/common"; -import { describe, expect, it } from "vitest"; - -import { Library } from "../../common/src/library/libraries/library"; -import { Relationship } from "../src/common/library/relationship-functions"; - -class StubLibrary extends Library { - private readonly _name: string; - - constructor(name: string, options?: ConstructorParameters[0]) { - super(options); - this._name = name; - } - - get __name(): string { - return this._name; - } -} - -const makeHandle = ( - sym: symbol, - name: string, - options?: ConstructorParameters[0], -): LibraryHandle => { - return new LibraryHandle( - sym, - new StubLibrary(name, options) as unknown as ILibrary, - new LibraryContext(), - ); -}; - -describe("Relationship.getLibrariesByDependencies", () => { - it("should return libraries in same order when no dependencies are declared", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleA = makeHandle(symA, "A"); - const handleB = makeHandle(symB, "B"); - - const result = Relationship.getLibrariesByDependencies([handleA, handleB]); - expect(result.map((h) => h.library.__name)).toEqual(["A", "B"]); - }); - - it("should put a dependency before the library that depends on it", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleB = makeHandle(symB, "B"); - const handleA = makeHandle(symA, "A", { dependencies: [symB] }); - - const result = Relationship.getLibrariesByDependencies([handleA, handleB]); - const names = result.map((h) => h.library.__name); - expect(names.indexOf("B")).toBeLessThan(names.indexOf("A")); - }); - - it("should not duplicate a shared dependency", () => { - const symDep = Symbol("Dep"); - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleDep = makeHandle(symDep, "Dep"); - const handleA = makeHandle(symA, "A", { dependencies: [symDep] }); - const handleB = makeHandle(symB, "B", { dependencies: [symDep] }); - - const result = Relationship.getLibrariesByDependencies([handleA, handleB, handleDep]); - const names = result.map((h) => h.library.__name); - expect(names.filter((n) => n === "Dep")).toHaveLength(1); - }); - - it("should return libraries in reverse dependency order when reverse=true", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleB = makeHandle(symB, "B"); - const handleA = makeHandle(symA, "A", { dependencies: [symB] }); - - const result = Relationship.getLibrariesByDependencies([handleA, handleB], true); - const names = result.map((h) => h.library.__name); - expect(names.indexOf("A")).toBeLessThan(names.indexOf("B")); - }); - - it("should throw on circular dependencies", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleA = makeHandle(symA, "A", { dependencies: [symB] }); - const handleB = makeHandle(symB, "B", { dependencies: [symA] }); - - expect(() => Relationship.getLibrariesByDependencies([handleA, handleB])).toThrow( - /[Cc]ircular/, - ); - }); -}); - -describe("Relationship.getLibrariesByRun", () => { - it("should return all runner libraries when no ordering is specified", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleA = makeHandle(symA, "A"); - const handleB = makeHandle(symB, "B"); - - const result = Relationship.getLibrariesByRun([handleA, handleB]); - expect(result).toHaveLength(2); - }); - - it("should place a library before another when runBefore is set", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleA = makeHandle(symA, "A", { runBefore: [symB] }); - const handleB = makeHandle(symB, "B"); - - const result = Relationship.getLibrariesByRun([handleA, handleB]); - const names = result.map((h) => h.library.__name); - expect(names.indexOf("B")).toBeLessThan(names.indexOf("A")); - }); - - it("should place a library after another when runAfter is set", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleA = makeHandle(symA, "A"); - const handleB = makeHandle(symB, "B", { runAfter: [symA] }); - - const result = Relationship.getLibrariesByRun([handleA, handleB]); - const names = result.map((h) => h.library.__name); - expect(names.indexOf("B")).toBeLessThan(names.indexOf("A")); - }); - - it("should throw on circular run dependencies", () => { - const symA = Symbol("A"); - const symB = Symbol("B"); - const handleA = makeHandle(symA, "A", { runBefore: [symB] }); - const handleB = makeHandle(symB, "B", { runBefore: [symA] }); - - expect(() => Relationship.getLibrariesByRun([handleA, handleB])).toThrow(/[Cc]ircular/); - }); - - it("should return empty array for empty input", () => { - expect(Relationship.getLibrariesByRun([])).toHaveLength(0); - }); -}); From 3af4c911f4577235a15f5e7493cb32b7dfaabf30 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 17:32:27 +0200 Subject: [PATCH 11/12] fix: change example and e2e games to the new architecture (#426) * fix: change example and e2e games to the new architecture * fix: change example and e2e games to the new architecture --- e2e/game/apps/client/nanoforge.config.ts | 5 +++ e2e/game/apps/client/package.json | 32 +++++++++++++++++ .../src}/components/example.component.ts | 2 +- e2e/game/{client => apps/client/src}/main.ts | 31 +++++++--------- .../client/src}/systems/example.system.ts | 2 +- e2e/game/apps/server/nanoforge.config.ts | 5 +++ e2e/game/apps/server/package.json | 30 ++++++++++++++++ .../src}/components/example.component.ts | 2 +- e2e/game/{server => apps/server/src}/main.ts | 20 ++++------- .../server/src}/systems/example.system.ts | 2 +- e2e/game/apps/server/src/ticker.library.ts | 35 +++++++++++++++++++ e2e/game/nanoforge.config.json | 21 ----------- e2e/game/nanoforge.config.ts | 6 ++++ e2e/game/package.json | 11 ++---- e2e/game/server/ticker.library.ts | 32 ----------------- e2e/run-server.mjs | 2 +- .../pong-network}/.prettierignore | 0 example/pong-network/apps/client/package.json | 5 ++- example/pong-network/apps/client/src/main.ts | 8 ++--- .../apps/client/src/systems/systems.ts | 2 +- .../pong-network/apps/client/tsconfig.json | 6 ++++ example/pong-network/apps/server/package.json | 5 ++- example/pong-network/apps/server/src/main.ts | 4 +-- .../apps/server/src/systems/systems.ts | 17 +++++---- .../pong-network/apps/server/tsconfig.json | 6 ++++ .../pong-network}/eslint.config.js | 0 example/pong-network/index.d.ts | 2 +- example/pong-network/package.json | 2 -- .../pong-network}/prettier.config.js | 0 .../pong-network/test/pong-network.spec.ts | 15 ++++++++ example/pong-network/tsconfig.spec.json | 10 ++++++ pnpm-workspace.yaml | 4 +-- 32 files changed, 202 insertions(+), 122 deletions(-) create mode 100644 e2e/game/apps/client/nanoforge.config.ts create mode 100644 e2e/game/apps/client/package.json rename e2e/game/{client => apps/client/src}/components/example.component.ts (99%) rename e2e/game/{client => apps/client/src}/main.ts (60%) rename e2e/game/{server => apps/client/src}/systems/example.system.ts (97%) create mode 100644 e2e/game/apps/server/nanoforge.config.ts create mode 100644 e2e/game/apps/server/package.json rename e2e/game/{server => apps/server/src}/components/example.component.ts (99%) rename e2e/game/{server => apps/server/src}/main.ts (56%) rename e2e/game/{client => apps/server/src}/systems/example.system.ts (97%) create mode 100644 e2e/game/apps/server/src/ticker.library.ts delete mode 100644 e2e/game/nanoforge.config.json create mode 100644 e2e/game/nanoforge.config.ts delete mode 100644 e2e/game/server/ticker.library.ts rename {packages/asset-manager => example/pong-network}/.prettierignore (100%) create mode 100644 example/pong-network/apps/client/tsconfig.json create mode 100644 example/pong-network/apps/server/tsconfig.json rename {packages/asset-manager => example/pong-network}/eslint.config.js (100%) rename {packages/asset-manager => example/pong-network}/prettier.config.js (100%) create mode 100644 example/pong-network/test/pong-network.spec.ts create mode 100644 example/pong-network/tsconfig.spec.json diff --git a/e2e/game/apps/client/nanoforge.config.ts b/e2e/game/apps/client/nanoforge.config.ts new file mode 100644 index 00000000..d220af78 --- /dev/null +++ b/e2e/game/apps/client/nanoforge.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "client", +}); diff --git a/e2e/game/apps/client/package.json b/e2e/game/apps/client/package.json new file mode 100644 index 00000000..64c59bd6 --- /dev/null +++ b/e2e/game/apps/client/package.json @@ -0,0 +1,32 @@ +{ + "name": "e2e-client", + "version": "0.0.0", + "description": "", + "author": "", + "scripts": { + "build": "nf build", + "start": "nf start", + "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"", + "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"" + }, + "devDependencies": { + "@nanoforge-dev/asset": "workspace:*", + "@nanoforge-dev/common": "workspace:*", + "@nanoforge-dev/core": "workspace:*", + "@nanoforge-dev/env": "workspace:*", + "@nanoforge-dev/ecs": "workspace:*", + "@nanoforge-dev/network": "workspace:*", + "@nanoforge-dev/graphics-2d": "workspace:*", + "@nanoforge-dev/input": "workspace:*", + "typescript": "catalog:core" + }, + "private": true, + "lint-staged": { + "**": [ + "prettier --ignore-unknown --write" + ], + "{client,server}/**/*.ts": [ + "eslint --fix" + ] + } +} diff --git a/e2e/game/client/components/example.component.ts b/e2e/game/apps/client/src/components/example.component.ts similarity index 99% rename from e2e/game/client/components/example.component.ts rename to e2e/game/apps/client/src/components/example.component.ts index 4e16c688..25f486bd 100644 --- a/e2e/game/client/components/example.component.ts +++ b/e2e/game/apps/client/src/components/example.component.ts @@ -1,4 +1,4 @@ -import { type EditorComponentManifest } from "@nanoforge-dev/ecs-client"; +import { type EditorComponentManifest } from "@nanoforge-dev/ecs/client"; export class ExampleComponent { name = this.constructor.name; diff --git a/e2e/game/client/main.ts b/e2e/game/apps/client/src/main.ts similarity index 60% rename from e2e/game/client/main.ts rename to e2e/game/apps/client/src/main.ts index 0f2057d1..989aa900 100644 --- a/e2e/game/client/main.ts +++ b/e2e/game/apps/client/src/main.ts @@ -1,36 +1,31 @@ -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { type IRunOptions } from "@nanoforge-dev/common"; +import type { ClientRunOptions } from "@nanoforge-dev/common"; import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSClientLibrary } from "@nanoforge-dev/ecs-client"; +import { EcsLibrary } from "@nanoforge-dev/ecs/client"; import { Graphics2DLibrary } from "@nanoforge-dev/graphics-2d"; import { InputLibrary } from "@nanoforge-dev/input"; import { MusicLibrary } from "@nanoforge-dev/music"; -import { NetworkClientLibrary } from "@nanoforge-dev/network-client"; +import { NetworkClientLibrary } from "@nanoforge-dev/network/client"; import { SoundLibrary } from "@nanoforge-dev/sound"; import { ExampleComponent } from "./components/example.component"; import { exampleSystem } from "./systems/example.system"; -export async function main(options: IRunOptions) { - const app = NanoforgeFactory.createClient({ - tickRate: 60, - }); +export const main = async (options: ClientRunOptions): Promise => { + const app = NanoforgeFactory.createClient({ tickRate: 60 }); - const assetManager = new AssetManagerLibrary(); - const ecs = new ECSClientLibrary(); const graphics = new Graphics2DLibrary(); + const ecs = new EcsLibrary(); const input = new InputLibrary(); const music = new MusicLibrary(); const network = new NetworkClientLibrary(); const sound = new SoundLibrary(); - app.useAssetManager(assetManager); - app.useComponentSystem(ecs); - app.useGraphics(graphics); - app.useInput(input); - app.useSound(sound); - app.useNetwork(network); - app.use(Symbol("music"), music); + app.use(graphics); + app.use(ecs); + app.use(input); + app.use(music); + app.use(network); + app.use(sound); await app.init({ ...options, @@ -50,4 +45,4 @@ export async function main(options: IRunOptions) { registry.addSystem(exampleSystem); await app.run(); -} +}; diff --git a/e2e/game/server/systems/example.system.ts b/e2e/game/apps/client/src/systems/example.system.ts similarity index 97% rename from e2e/game/server/systems/example.system.ts rename to e2e/game/apps/client/src/systems/example.system.ts index 7400df48..84552fb6 100644 --- a/e2e/game/server/systems/example.system.ts +++ b/e2e/game/apps/client/src/systems/example.system.ts @@ -1,5 +1,5 @@ import { type Context } from "@nanoforge-dev/common"; -import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-server"; +import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs/client"; import { ExampleComponent } from "../components/example.component"; diff --git a/e2e/game/apps/server/nanoforge.config.ts b/e2e/game/apps/server/nanoforge.config.ts new file mode 100644 index 00000000..bc5491cb --- /dev/null +++ b/e2e/game/apps/server/nanoforge.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "server", +}); diff --git a/e2e/game/apps/server/package.json b/e2e/game/apps/server/package.json new file mode 100644 index 00000000..805853d9 --- /dev/null +++ b/e2e/game/apps/server/package.json @@ -0,0 +1,30 @@ +{ + "name": "e2e-server", + "version": "0.0.0", + "description": "", + "author": "", + "scripts": { + "build": "nf build", + "start": "nf start", + "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"", + "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"" + }, + "devDependencies": { + "@nanoforge-dev/asset": "workspace:*", + "@nanoforge-dev/common": "workspace:*", + "@nanoforge-dev/core": "workspace:*", + "@nanoforge-dev/env": "workspace:*", + "@nanoforge-dev/ecs": "workspace:*", + "@nanoforge-dev/network": "workspace:*", + "typescript": "catalog:core" + }, + "private": true, + "lint-staged": { + "**": [ + "prettier --ignore-unknown --write" + ], + "{client,server}/**/*.ts": [ + "eslint --fix" + ] + } +} diff --git a/e2e/game/server/components/example.component.ts b/e2e/game/apps/server/src/components/example.component.ts similarity index 99% rename from e2e/game/server/components/example.component.ts rename to e2e/game/apps/server/src/components/example.component.ts index 6957308b..39d9fce0 100644 --- a/e2e/game/server/components/example.component.ts +++ b/e2e/game/apps/server/src/components/example.component.ts @@ -1,4 +1,4 @@ -import { type EditorComponentManifest } from "@nanoforge-dev/ecs-server"; +import { type EditorComponentManifest } from "@nanoforge-dev/ecs/server"; export class ExampleComponent { name = this.constructor.name; diff --git a/e2e/game/server/main.ts b/e2e/game/apps/server/src/main.ts similarity index 56% rename from e2e/game/server/main.ts rename to e2e/game/apps/server/src/main.ts index b2e236c0..0fef76aa 100644 --- a/e2e/game/server/main.ts +++ b/e2e/game/apps/server/src/main.ts @@ -1,25 +1,19 @@ -import { AssetManagerLibrary } from "@nanoforge-dev/asset-manager"; -import { type IRunOptions } from "@nanoforge-dev/common"; +import { type RunOptions } from "@nanoforge-dev/common"; import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { ECSServerLibrary } from "@nanoforge-dev/ecs-server"; +import { EcsLibrary } from "@nanoforge-dev/ecs/server"; import { ExampleComponent } from "./components/example.component"; import { exampleSystem } from "./systems/example.system"; import { TickerLibrary } from "./ticker.library"; -const TICKER = Symbol.for("ticker"); - -export async function main(options: IRunOptions) { +export const main = async (options: RunOptions): Promise => { const app = NanoforgeFactory.createServer({ tickRate: 60 }); - const assetManager = new AssetManagerLibrary(); - const ecs = new ECSServerLibrary(); - + const ecs = new EcsLibrary(); const ticker = new TickerLibrary(5); - app.useAssetManager(assetManager); - app.useComponentSystem(ecs); - app.use(TICKER, ticker); + app.use(ecs); + app.use(ticker); await app.init(options); @@ -33,4 +27,4 @@ export async function main(options: IRunOptions) { await app.run(); await ticker.done; -} +}; diff --git a/e2e/game/client/systems/example.system.ts b/e2e/game/apps/server/src/systems/example.system.ts similarity index 97% rename from e2e/game/client/systems/example.system.ts rename to e2e/game/apps/server/src/systems/example.system.ts index 39625aad..34b06e0a 100644 --- a/e2e/game/client/systems/example.system.ts +++ b/e2e/game/apps/server/src/systems/example.system.ts @@ -1,5 +1,5 @@ import { type Context } from "@nanoforge-dev/common"; -import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-client"; +import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs/server"; import { ExampleComponent } from "../components/example.component"; diff --git a/e2e/game/apps/server/src/ticker.library.ts b/e2e/game/apps/server/src/ticker.library.ts new file mode 100644 index 00000000..44d10098 --- /dev/null +++ b/e2e/game/apps/server/src/ticker.library.ts @@ -0,0 +1,35 @@ +import { type Context, defineLibraryKey, Library } from "@nanoforge-dev/common"; + +declare module "@nanoforge-dev/common" { + interface Context { + ticker: unknown; + } +} + +/** + * Stops the game loop after a fixed number of ticks. + * Exposes `done`, which resolves once the loop has stopped. + */ +export class TickerLibrary extends Library { + readonly key = defineLibraryKey("ticker"); + + private _remaining: number; + private _resolve!: () => void; + + public readonly done: Promise = new Promise((resolve) => { + this._resolve = resolve; + }); + + constructor(ticks: number) { + super(); + this._remaining = ticks; + } + + public override async __run(ctx: Context): Promise { + this._remaining--; + if (this._remaining <= 0) { + ctx.app.requestStop(); + this._resolve(); + } + } +} diff --git a/e2e/game/nanoforge.config.json b/e2e/game/nanoforge.config.json deleted file mode 100644 index 1e4becd5..00000000 --- a/e2e/game/nanoforge.config.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "client": { - "build": { - "entryFile": "client/main.ts", - "outDir": ".nanoforge/client" - }, - "runtime": { - "dir": ".nanoforge/client" - } - }, - "server": { - "enable": true, - "build": { - "entryFile": "server/main.ts", - "outDir": ".nanoforge/server" - }, - "runtime": { - "dir": ".nanoforge/server" - } - } -} diff --git a/e2e/game/nanoforge.config.ts b/e2e/game/nanoforge.config.ts new file mode 100644 index 00000000..1bbf8d4d --- /dev/null +++ b/e2e/game/nanoforge.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from "nanoforge/config"; + +export default defineConfig({ + type: "workspace", + packages: ["apps/*"], +}); diff --git a/e2e/game/package.json b/e2e/game/package.json index 8c5a4e56..16460ace 100644 --- a/e2e/game/package.json +++ b/e2e/game/package.json @@ -9,18 +9,11 @@ "start": "nf start" }, "devDependencies": { - "@nanoforge-dev/asset-manager": "workspace:*", + "@nanoforge-dev/asset": "workspace:*", "@nanoforge-dev/cli": "latest", "@nanoforge-dev/common": "workspace:*", "@nanoforge-dev/core": "workspace:*", - "@nanoforge-dev/ecs-client": "workspace:*", - "@nanoforge-dev/ecs-server": "workspace:*", - "@nanoforge-dev/graphics-2d": "workspace:*", - "@nanoforge-dev/input": "workspace:*", - "@nanoforge-dev/music": "workspace:*", - "@nanoforge-dev/network-client": "workspace:*", - "@nanoforge-dev/network-server": "workspace:*", - "@nanoforge-dev/sound": "workspace:*", + "@nanoforge-dev/env": "workspace:*", "typescript": "catalog:core" }, "private": true, diff --git a/e2e/game/server/ticker.library.ts b/e2e/game/server/ticker.library.ts deleted file mode 100644 index de5729a3..00000000 --- a/e2e/game/server/ticker.library.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BaseNetworkLibrary, type Context } from "@nanoforge-dev/common"; - -/** - * A runner library that stops the game loop after a fixed number of ticks. - * Reuses BaseNetworkLibrary (no abstract methods) so it can be registered - * as a standard library. Exposes `done` which resolves when the game stops. - */ -export class TickerLibrary extends BaseNetworkLibrary { - private _remaining: number; - private _resolve!: () => void; - - public readonly done: Promise = new Promise((resolve) => { - this._resolve = resolve; - }); - - constructor(ticks: number) { - super(); - this._remaining = ticks; - } - - get __name(): string { - return "TickerLibrary"; - } - - async __run(ctx: Context): Promise { - this._remaining--; - if (this._remaining <= 0) { - ctx.app.setIsRunning(false); - this._resolve(); - } - } -} diff --git a/e2e/run-server.mjs b/e2e/run-server.mjs index 5a183bb4..0324f3c8 100644 --- a/e2e/run-server.mjs +++ b/e2e/run-server.mjs @@ -4,7 +4,7 @@ import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const PROJECT_DIR = resolve(__dirname, "./game"); -const wasmPath = resolve(PROJECT_DIR, "../../packages/ecs-server/dist/assets/libecs.wasm"); +const wasmPath = resolve(PROJECT_DIR, "../../modules/ecs/lib/node/libecs.wasm"); const timeout = setTimeout(() => { console.error("[E2E] Server timed out after 10s — aborting"); diff --git a/packages/asset-manager/.prettierignore b/example/pong-network/.prettierignore similarity index 100% rename from packages/asset-manager/.prettierignore rename to example/pong-network/.prettierignore diff --git a/example/pong-network/apps/client/package.json b/example/pong-network/apps/client/package.json index 246b97c8..6a4344a1 100644 --- a/example/pong-network/apps/client/package.json +++ b/example/pong-network/apps/client/package.json @@ -12,11 +12,10 @@ "devDependencies": { "@nanoforge-dev/asset": "workspace:*", "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/config": "workspace:*", "@nanoforge-dev/core": "workspace:*", "@nanoforge-dev/env": "workspace:*", - "@nanoforge-dev/ecs-client": "workspace:*", - "@nanoforge-dev/network-client": "workspace:*", + "@nanoforge-dev/ecs": "workspace:*", + "@nanoforge-dev/network": "workspace:*", "@nanoforge-dev/graphics-2d": "workspace:*", "@nanoforge-dev/input": "workspace:*", "@nanoforge-dev/utils-eslint-config": "workspace:*", diff --git a/example/pong-network/apps/client/src/main.ts b/example/pong-network/apps/client/src/main.ts index 4f1df8b2..bfebd2d3 100644 --- a/example/pong-network/apps/client/src/main.ts +++ b/example/pong-network/apps/client/src/main.ts @@ -1,9 +1,9 @@ import type { ClientRunOptions } from "@nanoforge-dev/common"; import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { EcsLibrary } from "@nanoforge-dev/ecs-client"; +import { EcsLibrary } from "@nanoforge-dev/ecs/client"; import { Circle, Graphics2DLibrary, Layer, Rect } from "@nanoforge-dev/graphics-2d"; import { InputEnum, InputLibrary } from "@nanoforge-dev/input"; -import { NetworkClientLibrary } from "@nanoforge-dev/network-client"; +import { NetworkClientLibrary } from "@nanoforge-dev/network/client"; import { CircleComponent, @@ -89,7 +89,7 @@ export const main = async (options: ClientRunOptions): Promise => { return new Promise((resolve) => { const check = () => { - if (network.tcp.isConnected()) { + if (network.tcp?.isConnected()) { resolve(); } else { setTimeout(check, 50); @@ -100,7 +100,7 @@ export const main = async (options: ClientRunOptions): Promise => { } await waitForConnection(); - network.tcp.sendData(new TextEncoder().encode(JSON.stringify({ type: "play" }))); + network.tcp?.sendData(new TextEncoder().encode(JSON.stringify({ type: "play" }))); await app.run(); }; diff --git a/example/pong-network/apps/client/src/systems/systems.ts b/example/pong-network/apps/client/src/systems/systems.ts index f183f350..d3b41fad 100644 --- a/example/pong-network/apps/client/src/systems/systems.ts +++ b/example/pong-network/apps/client/src/systems/systems.ts @@ -1,5 +1,5 @@ import { type Context } from "@nanoforge-dev/common"; -import { type Registry } from "@nanoforge-dev/ecs-client"; +import { type Registry } from "@nanoforge-dev/ecs/client"; import { CircleComponent, diff --git a/example/pong-network/apps/client/tsconfig.json b/example/pong-network/apps/client/tsconfig.json new file mode 100644 index 00000000..f90a806b --- /dev/null +++ b/example/pong-network/apps/client/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", ".nanoforge"] +} diff --git a/example/pong-network/apps/server/package.json b/example/pong-network/apps/server/package.json index 710ef94f..e163e437 100644 --- a/example/pong-network/apps/server/package.json +++ b/example/pong-network/apps/server/package.json @@ -12,11 +12,10 @@ "devDependencies": { "@nanoforge-dev/asset": "workspace:*", "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/config": "workspace:*", "@nanoforge-dev/core": "workspace:*", "@nanoforge-dev/env": "workspace:*", - "@nanoforge-dev/ecs-server": "workspace:*", - "@nanoforge-dev/network-server": "workspace:*", + "@nanoforge-dev/ecs": "workspace:*", + "@nanoforge-dev/network": "workspace:*", "@nanoforge-dev/utils-eslint-config": "workspace:*", "@nanoforge-dev/utils-prettier-config": "workspace:*", "@trivago/prettier-plugin-sort-imports": "catalog:lint", diff --git a/example/pong-network/apps/server/src/main.ts b/example/pong-network/apps/server/src/main.ts index 435454bb..f90b95a0 100644 --- a/example/pong-network/apps/server/src/main.ts +++ b/example/pong-network/apps/server/src/main.ts @@ -1,7 +1,7 @@ import type { RunOptions } from "@nanoforge-dev/common"; import { NanoforgeFactory } from "@nanoforge-dev/core"; -import { EcsLibrary } from "@nanoforge-dev/ecs-server"; -import { NetworkServerLibrary } from "@nanoforge-dev/network-server"; +import { EcsLibrary } from "@nanoforge-dev/ecs/server"; +import { NetworkServerLibrary } from "@nanoforge-dev/network/server"; import { Position, Velocity } from "./components/components"; import { bounce, move, packetHandler } from "./systems/systems"; diff --git a/example/pong-network/apps/server/src/systems/systems.ts b/example/pong-network/apps/server/src/systems/systems.ts index a16d75c3..c119dca8 100644 --- a/example/pong-network/apps/server/src/systems/systems.ts +++ b/example/pong-network/apps/server/src/systems/systems.ts @@ -1,6 +1,6 @@ import { type Context } from "@nanoforge-dev/common"; -import { type Registry } from "@nanoforge-dev/ecs-server"; -import { type NetworkServerLibrary } from "@nanoforge-dev/network-server"; +import { type Registry } from "@nanoforge-dev/ecs/server"; +import { type NetworkServerContextApi } from "@nanoforge-dev/network/server"; import { Position, Velocity } from "../components/components"; @@ -19,7 +19,7 @@ export function move(registry: Registry, ctx: Context) { }); } -function sendMoveAll(id: number, vel: Velocity, pos: Position, network: NetworkServerLibrary) { +function sendMoveAll(id: number, vel: Velocity, pos: Position, network: NetworkServerContextApi) { network.tcp.sendToEverybody( new TextEncoder().encode( JSON.stringify({ @@ -32,7 +32,7 @@ function sendMoveAll(id: number, vel: Velocity, pos: Position, network: NetworkS ); } -function connectNewClient(newCli: number, network: NetworkServerLibrary, zip: any) { +function connectNewClient(newCli: number, network: NetworkServerContextApi, zip: any) { network.tcp.sendToClient( newCli, new TextEncoder().encode(JSON.stringify({ type: "assignId", assigned: "ball", id: 0 })), @@ -50,7 +50,12 @@ function connectNewClient(newCli: number, network: NetworkServerLibrary, zip: an sendMoveAll(2, zip[2].Velocity, zip[2].Position, network); } -function handleClientInput(clientId: number, key: string, network: NetworkServerLibrary, zip: any) { +function handleClientInput( + clientId: number, + key: string, + network: NetworkServerContextApi, + zip: any, +) { let id; if (clientId === cli1) { @@ -110,7 +115,7 @@ export function packetHandler(registry: Registry, ctx: Context) { }); } -function checkOutOfTerrain(id: number, paddle: any, network: NetworkServerLibrary) { +function checkOutOfTerrain(id: number, paddle: any, network: NetworkServerContextApi) { if (paddle.Position.y < 0) { paddle.Position.y = 0; paddle.Velocity.y = 0; diff --git a/example/pong-network/apps/server/tsconfig.json b/example/pong-network/apps/server/tsconfig.json new file mode 100644 index 00000000..f90a806b --- /dev/null +++ b/example/pong-network/apps/server/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", ".nanoforge"] +} diff --git a/packages/asset-manager/eslint.config.js b/example/pong-network/eslint.config.js similarity index 100% rename from packages/asset-manager/eslint.config.js rename to example/pong-network/eslint.config.js diff --git a/example/pong-network/index.d.ts b/example/pong-network/index.d.ts index ea737668..3e7f8b23 100644 --- a/example/pong-network/index.d.ts +++ b/example/pong-network/index.d.ts @@ -1,5 +1,5 @@ // Ambient stub for the `nf` CLI's own `nanoforge/config` resolution. Keep this -// shape in sync with @nanoforge-dev/config's real types; revisit/remove once +// shape in sync with @nanoforge-dev/env's real types; revisit/remove once // the CLI's actual resolution contract for `nanoforge.config.ts` is confirmed. declare module "nanoforge/config" { type ContainLibConfig = { diff --git a/example/pong-network/package.json b/example/pong-network/package.json index ab03589b..79cc5fc3 100644 --- a/example/pong-network/package.json +++ b/example/pong-network/package.json @@ -4,7 +4,6 @@ "description": "", "author": "", "scripts": { - "build": "mkdir -p .nanoforge && nf build", "start": "nf start", "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"", "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\"", @@ -14,7 +13,6 @@ "@nanoforge-dev/asset": "workspace:*", "@nanoforge-dev/cli": "latest", "@nanoforge-dev/common": "workspace:*", - "@nanoforge-dev/config": "workspace:*", "@nanoforge-dev/core": "workspace:*", "@nanoforge-dev/env": "workspace:*", "@trivago/prettier-plugin-sort-imports": "catalog:lint", diff --git a/packages/asset-manager/prettier.config.js b/example/pong-network/prettier.config.js similarity index 100% rename from packages/asset-manager/prettier.config.js rename to example/pong-network/prettier.config.js diff --git a/example/pong-network/test/pong-network.spec.ts b/example/pong-network/test/pong-network.spec.ts new file mode 100644 index 00000000..6f06d624 --- /dev/null +++ b/example/pong-network/test/pong-network.spec.ts @@ -0,0 +1,15 @@ +import { describe, expect, it } from "vitest"; + +import { main as clientMain } from "../apps/client/src/main"; +import { main as serverMain } from "../apps/server/src/main"; + +describe("pong-network plumbing skeleton", () => { + it("server app runs its tick loop and stops cleanly", async () => { + await expect(serverMain({ files: new Map(), env: {} })).resolves.toBeUndefined(); + }); + + it("client app runs its tick loop, writes vars, and stops cleanly", async () => { + const container = {} as unknown as HTMLDivElement; + await expect(clientMain({ files: new Map(), env: {}, container })).resolves.toBeUndefined(); + }); +}); diff --git a/example/pong-network/tsconfig.spec.json b/example/pong-network/tsconfig.spec.json new file mode 100644 index 00000000..bbad15dc --- /dev/null +++ b/example/pong-network/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "skipLibCheck": true + }, + "include": ["apps/*/src/**/*.ts", "test/**/*.spec.ts"], + "exclude": ["node_modules"] +} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bfa59cce..3b19f0e6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,8 +1,8 @@ packages: - packages/* - utils/* - - e2e/game - - example/* + - e2e/game/** + - example/** allowBuilds: bun: true From ca14fcb14e315301887795c65dee295afde68bb9 Mon Sep 17 00:00:00 2001 From: Exelo Date: Sun, 30 Aug 2026 17:36:19 +0200 Subject: [PATCH 12/12] chore: change misc (#427) --- .github/CODEOWNERS | 8 +- .../ISSUE_TEMPLATE/01-packages_bug_report.yml | 16 +- .../ISSUE_TEMPLATE/02-utils_bug_report.yml | 2 +- .github/ISSUE_TEMPLATE/03-feature_request.yml | 14 +- .github/issue-labeler.yml | 60 +- .github/labeler.yml | 100 +- .github/labels.yml | 74 +- .github/workflows/alpha-release.yml | 14 +- .github/workflows/pre-release.yml | 2 +- .github/workflows/release.yml | 2 +- .gitignore | 2 + .idea/[NanoForge] Engine.iml | 67 +- .prettierignore | 1 + package.json | 5 +- pnpm-lock.yaml | 1840 ++++++----------- pnpm-workspace.yaml | 5 +- tsdown.config.ts | 11 +- .../input => utils/eslint-config}/.gitignore | 41 - utils/eslint-config/LICENSE | 2 +- utils/eslint-config/README.md | 2 +- utils/eslint-config/package.json | 5 +- .../prettier-config}/.gitignore | 41 - utils/prettier-config/LICENSE | 2 +- utils/prettier-config/README.md | 2 +- utils/prettier-config/package.json | 5 +- 25 files changed, 797 insertions(+), 1526 deletions(-) rename {packages/input => utils/eslint-config}/.gitignore (91%) rename {packages/sound => utils/prettier-config}/.gitignore (91%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1fcdda08..bb68c8b4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,12 +1,8 @@ * @Exeloo /packages/core @Tchips46 -/packages/core-editor @Tchips46 -/packages/ecs-client @MartinFillon @Tchips46 -/packages/ecs-lib @MartinFillon @Tchips46 -/packages/ecs-server @MartinFillon @Tchips46 -/packages/network-client @Tchips46 -/packages/network-server @Tchips46 +/modules/ecs @MartinFillon @Tchips46 +/modules/network @Tchips46 /scripts @MartinFillon /typedoc.* @MartinFillon diff --git a/.github/ISSUE_TEMPLATE/01-packages_bug_report.yml b/.github/ISSUE_TEMPLATE/01-packages_bug_report.yml index 469f0ed2..5f9af55b 100644 --- a/.github/ISSUE_TEMPLATE/01-packages_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/01-packages_bug_report.yml @@ -13,20 +13,16 @@ body: attributes: label: Which package is this bug report for? options: - - asset-manager + - asset - common - - config - core - - core-editor - - ecs-client - - ecs-lib - - ecs-server + - ecs + - editor + - env - graphics-2d - - graphics-2d-editor - input - music - - network-client - - network-server + - network - sound - other validations: @@ -63,7 +59,7 @@ body: description: List necessary versions here. This includes your package version, runtime version, operating system etc. placeholder: | - @nanoforge-dev/common 1.0.0 (`npm ls @nanoforge-dev/common` or another package) - - Node.js 25 (`node --version`) + - Node.js 26 (`node --version`) - TypeScript 5.9.3 (`npm ls typescript` if you use it) - macOS Ventura 13.3.1 validations: diff --git a/.github/ISSUE_TEMPLATE/02-utils_bug_report.yml b/.github/ISSUE_TEMPLATE/02-utils_bug_report.yml index 79f4425f..bc1c17f8 100644 --- a/.github/ISSUE_TEMPLATE/02-utils_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/02-utils_bug_report.yml @@ -38,7 +38,7 @@ body: description: List necessary versions here. This includes your package version, runtime version, operating system etc. placeholder: | - @nanoforge-dev/utils-eslint-config 1.0.0 (`npm ls @nanoforge-dev/utils-eslint-config` or another package) - - Node.js 25 (`node --version`) + - Node.js 26 (`node --version`) - TypeScript 5.9.3 (`npm ls typescript` if you use it) - macOS Ventura 13.3.1 validations: diff --git a/.github/ISSUE_TEMPLATE/03-feature_request.yml b/.github/ISSUE_TEMPLATE/03-feature_request.yml index 19c3b871..e8ad2b89 100644 --- a/.github/ISSUE_TEMPLATE/03-feature_request.yml +++ b/.github/ISSUE_TEMPLATE/03-feature_request.yml @@ -11,20 +11,16 @@ body: attributes: label: Which package or utils is this feature request for? options: - - asset-manager + - asset - common - - config - core - - core-editor - - ecs-client - - ecs-lib - - ecs-server + - ecs + - editor + - env - graphics-2d - - graphics-2d-editor - input - music - - network-client - - network-server + - network - sound - eslint-config - prettier-config diff --git a/.github/issue-labeler.yml b/.github/issue-labeler.yml index 450cdb9a..f880a66d 100644 --- a/.github/issue-labeler.yml +++ b/.github/issue-labeler.yml @@ -1,62 +1,46 @@ -packages:asset-manager: +modules:ecs: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\nasset-manager\\n" + report|feature request) for\\?\\n\\necs\\n" -packages:common: - - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\ncommon\\n" - -packages:config: - - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\nconfig\\n" - -packages:core: - - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\ncore\\n" - -packages:core-editor: - - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\ncore-editor\\n" - -packages:ecs-client: +modules:editor: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\necs-client\\n" + report|feature request) for\\?\\n\\neditor\\n" -packages:ecs-lib: +modules:graphics-2d: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\necs-lib\\n" + report|feature request) for\\?\\n\\ngraphics-2d\\n" -packages:ecs-server: +modules:input: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\necs-server\\n" + report|feature request) for\\?\\n\\ninput\\n" -packages:graphics-2d: +modules:music: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\ngraphics-2d\\n" + report|feature request) for\\?\\n\\nmusic\\n" -packages:graphics-2d-editor: +modules:network: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\ngraphics-2d-editor\\n" + report|feature request) for\\?\\n\\nnetwork\\n" -packages:input: +modules:sound: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\ninput\\n" + report|feature request) for\\?\\n\\nsound\\n" -packages:music: +packages:asset: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\nmusic\\n" + report|feature request) for\\?\\n\\nasset\\n" -packages:network-client: +packages:common: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\nnetwork-client\\n" + report|feature request) for\\?\\n\\ncommon\\n" -packages:network-server: +packages:core: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\nnetwork-server\\n" + report|feature request) for\\?\\n\\ncore\\n" -packages:sound: +packages:env: - "### Which (package|utils|package or utils) is this (bug - report|feature request) for\\?\\n\\nsound\\n" + report|feature request) for\\?\\n\\nenv\\n" utils:eslint-config: - "### Which (package|utils|package or utils) is this (bug diff --git a/.github/labeler.yml b/.github/labeler.yml index 311df846..1843dc1e 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,92 +1,76 @@ -packages:asset-manager: - - changed-files: - - any-glob-to-any-file: - - packages/asset-manager/* - - packages/asset-manager/**/* - -packages:common: - - changed-files: - - any-glob-to-any-file: - - packages/common/* - - packages/common/**/* - -packages:config: - - changed-files: - - any-glob-to-any-file: - - packages/config/* - - packages/config/**/* - -packages:core: +documentation: - changed-files: - any-glob-to-any-file: - - packages/core/* - - packages/core/**/* + - docs/* + - docs/**/* + - modules/ecs/docs/* + - modules/ecs/docs/**/* -packages:core-editor: +modules:ecs: - changed-files: - any-glob-to-any-file: - - packages/core-editor/* - - packages/core-editor/**/* + - modules/ecs/* + - modules/ecs/**/* -packages:ecs-client: +modules:editor: - changed-files: - any-glob-to-any-file: - - packages/ecs-client/* - - packages/ecs-client/**/* + - modules/editor/* + - modules/editor/**/* -packages:ecs-lib: +modules:graphics-2d: - changed-files: - any-glob-to-any-file: - - packages/ecs-lib/* - - packages/ecs-lib/**/* + - modules/graphics-2d/* + - modules/graphics-2d/**/* -packages:ecs-server: +modules:input: - changed-files: - any-glob-to-any-file: - - packages/ecs-server/* - - packages/ecs-server/**/* + - modules/input/* + - modules/input/**/* -packages:graphics-2d: +modules:music: - changed-files: - any-glob-to-any-file: - - packages/graphics-2d/* - - packages/graphics-2d/**/* + - modules/music/* + - modules/music/**/* -packages:graphics-2d-editor: +modules:network: - changed-files: - any-glob-to-any-file: - - packages/graphics-2d-editor/* - - packages/graphics-2d-editor/**/* + - modules/network/* + - modules/network/**/* -packages:input: +modules:sound: - changed-files: - any-glob-to-any-file: - - packages/input/* - - packages/input/**/* + - modules/sound/* + - modules/sound/**/* -packages:music: +packages:asset: - changed-files: - any-glob-to-any-file: - - packages/music/* - - packages/music/**/* + - packages/asset/* + - packages/asset/**/* -packages:network-client: +packages:common: - changed-files: - any-glob-to-any-file: - - packages/network-client/* - - packages/network-client/**/* + - packages/common/* + - packages/common/**/* -packages:network-server: +packages:core: - changed-files: - any-glob-to-any-file: - - packages/network-server/* - - packages/network-server/**/* + - packages/core/* + - packages/core/**/* -packages:sound: +packages:env: - changed-files: - any-glob-to-any-file: - - packages/sound/* - - packages/sound/**/* + - packages/env/* + - packages/env/**/* utils:eslint-config: - changed-files: @@ -99,11 +83,3 @@ utils:prettier-config: - any-glob-to-any-file: - utils/prettier-config/* - utils/prettier-config/**/* - -documentation: - - changed-files: - - any-glob-to-any-file: - - docs/* - - docs/**/* - - packages/ecs-lib/docs/* - - packages/ecs-lib/docs/**/* diff --git a/.github/labels.yml b/.github/labels.yml index ac53356d..cbcf9397 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -42,64 +42,48 @@ description: "This doesn't seem right" color: "e4e669" -- name: "packages:asset-manager" - description: "Related to AssetManager library" - color: "aaa3dc" +- name: "modules:ecs" + description: "Related to ECS library" + color: "1c3f78" -- name: "packages:common" - description: "Related to Common library" - color: "aaa3dc" - -- name: "packages:config" - description: "Related to Config library" - color: "aaa3dc" - -- name: "packages:core" - description: "Related to Core library" - color: "aaa3dc" - -- name: "packages:core-editor" - description: "Related to Core Editor library" - color: "aaa3dc" - -- name: "packages:ecs-client" - description: "Related to ECSClient library" - color: "aaa3dc" - -- name: "packages:ecs-lib" - description: "Related to Abstract ECS library" - color: "aaa3dc" +- name: "modules:editor" + description: "Related to Editor library" + color: "1c3f78" -- name: "packages:ecs-server" - description: "Related to ECSServer library" - color: "aaa3dc" - -- name: "packages:graphics-2d" +- name: "modules:graphics-2d" description: "Related to Graphics2D library" - color: "aaa3dc" - -- name: "packages:graphics-2d-editor" - description: "Related to Graphics2D Editor library" - color: "aaa3dc" + color: "1c3f78" -- name: "packages:input" +- name: "modules:input" description: "Related to Input library" - color: "aaa3dc" + color: "1c3f78" -- name: "packages:music" +- name: "modules:music" description: "Related to Music library" + color: "1c3f78" + +- name: "modules:network" + description: "Related to Network library" + color: "1c3f78" + +- name: "modules:sound" + description: "Related to Sound library" + color: "1c3f78" + +- name: "packages:asset" + description: "Related to AssetManager library" color: "aaa3dc" -- name: "packages:network-client" - description: "Related to NetworkClient library" +- name: "packages:common" + description: "Related to Common library" color: "aaa3dc" -- name: "packages:network-server" - description: "Related to NetworkServer library" +- name: "packages:core" + description: "Related to Core library" color: "aaa3dc" -- name: "packages:sound" - description: "Related to Sound library" +- name: "packages:env" + description: "Related to Env library" color: "aaa3dc" - name: "question" diff --git a/.github/workflows/alpha-release.yml b/.github/workflows/alpha-release.yml index 76fe91ea..e10eb915 100644 --- a/.github/workflows/alpha-release.yml +++ b/.github/workflows/alpha-release.yml @@ -8,20 +8,16 @@ on: type: choice required: true options: - - "@nanoforge-dev/asset-manager" + - "@nanoforge-dev/asset" - "@nanoforge-dev/common" - - "@nanoforge-dev/config" - "@nanoforge-dev/core" - - "@nanoforge-dev/core-editor" - - "@nanoforge-dev/ecs-client" - - "@nanoforge-dev/ecs-lib" - - "@nanoforge-dev/ecs-server" + - "@nanoforge-dev/ecs" + - "@nanoforge-dev/editor-lib" + - "@nanoforge-dev/env" - "@nanoforge-dev/graphics-2d" - - "@nanoforge-dev/graphics-2d-editor" - "@nanoforge-dev/input" - "@nanoforge-dev/music" - - "@nanoforge-dev/network-client" - - "@nanoforge-dev/network-server" + - "@nanoforge-dev/network" - "@nanoforge-dev/sound" - "@nanoforge-dev/utils-eslint-config" - "@nanoforge-dev/utils-prettier-config" diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index bfb55188..1af60574 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -34,7 +34,7 @@ jobs: - name: Create release PR uses: ./node_modules/@nanoforge-dev/actions/actions/create-packages-release-pr with: - packages: "@nanoforge-dev/asset-manager,@nanoforge-dev/common,@nanoforge-dev/config,@nanoforge-dev/core,@nanoforge-dev/core-editor,@nanoforge-dev/ecs-client,@nanoforge-dev/ecs-lib,@nanoforge-dev/ecs-server,@nanoforge-dev/graphics-2d,@nanoforge-dev/graphics-2d-editor,@nanoforge-dev/input,@nanoforge-dev/music,@nanoforge-dev/network-client,@nanoforge-dev/network-server,@nanoforge-dev/sound" + packages: "@nanoforge-dev/asset,@nanoforge-dev/common,@nanoforge-dev/core,@nanoforge-dev/ecs,@nanoforge-dev/editor-lib,@nanoforge-dev/env,@nanoforge-dev/graphics-2d,@nanoforge-dev/input,@nanoforge-dev/music,@nanoforge-dev/network,@nanoforge-dev/sound" version: ${{ inputs.version }} branch-format: "releases/nanoforge@{version}" commit-format: "chore: release @nanoforge-dev/engine@{version}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e7d15658..12d25e80 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: - name: Release packages uses: ./node_modules/@nanoforge-dev/actions/actions/release-packages with: - packages: "@nanoforge-dev/asset-manager,@nanoforge-dev/common,@nanoforge-dev/config,@nanoforge-dev/core,@nanoforge-dev/core-editor,@nanoforge-dev/ecs-client,@nanoforge-dev/ecs-lib,@nanoforge-dev/ecs-server,@nanoforge-dev/graphics-2d,@nanoforge-dev/graphics-2d-editor,@nanoforge-dev/input,@nanoforge-dev/music,@nanoforge-dev/network-client,@nanoforge-dev/network-server,@nanoforge-dev/sound" + packages: "@nanoforge-dev/asset,@nanoforge-dev/common,@nanoforge-dev/core,@nanoforge-dev/ecs,@nanoforge-dev/editor-lib,@nanoforge-dev/env,@nanoforge-dev/graphics-2d,@nanoforge-dev/input,@nanoforge-dev/music,@nanoforge-dev/network,@nanoforge-dev/sound" tag-format: "{version}" latest: true env: diff --git a/.gitignore b/.gitignore index 1279e044..a9ed69d0 100644 --- a/.gitignore +++ b/.gitignore @@ -241,3 +241,5 @@ emsdk-cache/ references/ .direnv + +packages/old-core/ \ No newline at end of file diff --git a/.idea/[NanoForge] Engine.iml b/.idea/[NanoForge] Engine.iml index fc5ad77e..94d8561a 100644 --- a/.idea/[NanoForge] Engine.iml +++ b/.idea/[NanoForge] Engine.iml @@ -11,48 +11,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + + + diff --git a/.prettierignore b/.prettierignore index 881beaab..98eca11c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,6 +7,7 @@ bun.lock pnpm-workspace.yaml packages/ +modules/ example/ utils/ releases/ diff --git a/package.json b/package.json index a893b2c5..c02f80b4 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "type": "module", @@ -48,7 +49,7 @@ "typescript": "catalog:core", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1608cfc4..18c6a80d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,3 +1,104 @@ +--- +lockfileVersion: '9.0' + +importers: + + .: + configDependencies: {} + packageManagerDependencies: + pnpm: + specifier: 12.0.0 + version: 12.0.0 + +packages: + + '@pnpm/exe.darwin-arm64@12.0.0': + resolution: {integrity: sha512-sqeoPfVMIfQhbwzDrKraXY2ynyuWClFqzvfImzAS/yczEru1m5SGvQ9kgFPDvQzJZ9AetedgJeDZC6qYvH8/tQ==} + cpu: [arm64] + os: [darwin] + + '@pnpm/exe.darwin-x64@12.0.0': + resolution: {integrity: sha512-Quc3J6c9cGTy+LDgz1cLVgCNOU9IERuyAlDoEj0DCilKqvo50Jx1GV8k74iwn4J9fFSKkm8JrwNvtTDj3uWnUA==} + cpu: [x64] + os: [darwin] + + '@pnpm/exe.linux-arm64-musl@12.0.0': + resolution: {integrity: sha512-EVWd3OTmgsMFhXx69b5JxIzoabG9Ma7m4OeTaf0ZKBzMnfYi8u21NDQo92ToMrdYL5dYDDCHsyYIjXzk+d0HhA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-arm64@12.0.0': + resolution: {integrity: sha512-cXHHW8M4rAPsYNkKZO9WVcpLLK55i9EaIsZPfIqUuY2eopd5LqnFyBge54HCh1GC0yCX8ySn0hYIi+4OyAEoDg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.linux-x64-musl@12.0.0': + resolution: {integrity: sha512-UcXwMdFjly0mpddkGigHKTxe27IMv2fUK4IWW/MHmJ3yMguxXmkwNlEI4aE+G1HO2TLo20uNEUWD4ymLe/DaCQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@pnpm/exe.linux-x64@12.0.0': + resolution: {integrity: sha512-6Rsl+zEWMOmus7v7/9J3OE8EMvHyNAfxYmDfmhQG4J0985OuT3G3Ho9NSGHjkBn4aU4bgklWifRhe1HX8dUSyw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@pnpm/exe.win32-arm64@12.0.0': + resolution: {integrity: sha512-O5F76A4oVFrpDGdFxEszRIThOSBfjHdH5c006gR+7UTCfiXrukr1XfqPungUI1DXcSR5gb9jBsPQqQZOAoOOxw==} + cpu: [arm64] + os: [win32] + + '@pnpm/exe.win32-x64@12.0.0': + resolution: {integrity: sha512-5dKFajIEWJ1ai+KHXFJvskY6vchbunmLwSUV2ywbLymcmJjfY5XJVpgzPCyIoVCMVG0zHorr66+hM8h8b3aRfQ==} + cpu: [x64] + os: [win32] + + pnpm@12.0.0: + resolution: {integrity: sha512-ni49w5EZlYaNyUuBdcIXwn6VQI+gO0oidJd48rNPdzt3zdOznt6BcbIvzVO+ajU0Lp+smUimjvWN9kiM6Jp+Zw==} + engines: {node: '>=18.*'} + hasBin: true + +snapshots: + + '@pnpm/exe.darwin-arm64@12.0.0': + optional: true + + '@pnpm/exe.darwin-x64@12.0.0': + optional: true + + '@pnpm/exe.linux-arm64-musl@12.0.0': + optional: true + + '@pnpm/exe.linux-arm64@12.0.0': + optional: true + + '@pnpm/exe.linux-x64-musl@12.0.0': + optional: true + + '@pnpm/exe.linux-x64@12.0.0': + optional: true + + '@pnpm/exe.win32-arm64@12.0.0': + optional: true + + '@pnpm/exe.win32-x64@12.0.0': + optional: true + + pnpm@12.0.0: + optionalDependencies: + '@pnpm/exe.darwin-arm64': 12.0.0 + '@pnpm/exe.darwin-x64': 12.0.0 + '@pnpm/exe.linux-arm64': 12.0.0 + '@pnpm/exe.linux-arm64-musl': 12.0.0 + '@pnpm/exe.linux-x64': 12.0.0 + '@pnpm/exe.linux-x64-musl': 12.0.0 + '@pnpm/exe.win32-arm64': 12.0.0 + '@pnpm/exe.win32-x64': 12.0.0 + +--- lockfileVersion: '9.0' settings: @@ -29,8 +130,8 @@ catalogs: specifier: ^9.1.7 version: 9.1.7 lint-staged: - specifier: ^17.3.0 - version: 17.3.0 + specifier: ^17.4.1 + version: 17.4.1 config: class-transformer: specifier: ^0.5.1 @@ -46,8 +147,8 @@ catalogs: specifier: ^2.10.12 version: 2.10.12 typescript: - specifier: ^7.0.2 - version: 7.0.2 + specifier: ^6.0.3 + version: 6.0.3 docs: '@microsoft/api-extractor': specifier: ^7.59.0 @@ -58,7 +159,7 @@ catalogs: graphics: konva: specifier: ^10.2.3 - version: 10.3.0 + version: 10.3.2 lint: '@eslint/js': specifier: ^10.0.1 @@ -83,13 +184,13 @@ catalogs: version: 5.5.6 globals: specifier: ^17.3.0 - version: 17.7.0 + version: 17.11.0 prettier: specifier: ^3.9.6 version: 3.9.6 typescript-eslint: specifier: ^8.61.0 - version: 8.62.0 + version: 8.68.0 network: '@mapbox/node-pre-gyp': specifier: ^2.0.3 @@ -102,7 +203,7 @@ catalogs: version: 0.4.7 ws: specifier: ^8.20.1 - version: 8.21.0 + version: 8.21.3 test: '@vitest/coverage-v8': specifier: ^4.1.11 @@ -117,7 +218,7 @@ importers: devDependencies: '@commitlint/cli': specifier: catalog:ci - version: 21.2.2(@types/node@26.4.0)(conventional-commits-parser@7.1.2)(typescript@7.0.2) + version: 21.2.2(@types/node@26.4.0)(conventional-commits-parser@7.1.2)(typescript@6.0.3) '@commitlint/config-conventional': specifier: catalog:ci version: 21.2.2 @@ -150,115 +251,43 @@ importers: version: 9.1.7 lint-staged: specifier: catalog:ci - version: 17.3.0 + version: 17.4.1 mint-tsdocs: specifier: catalog:docs - version: 0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.4.0)(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(react-dom@18.3.1(react@18.3.1))(supports-color@10.2.2)(typescript@7.0.2) + version: 0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.4.0)(@typescript-eslint/parser@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(react-dom@18.3.1(react@18.3.1))(supports-color@10.2.2)(typescript@6.0.3) prettier: specifier: catalog:lint version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) turbo: specifier: catalog:core version: 2.10.12 typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - - e2e/game: - devDependencies: - '@nanoforge-dev/asset-manager': - specifier: workspace:* - version: link:../../packages/asset-manager - '@nanoforge-dev/cli': - specifier: latest - version: 1.6.2(@types/node@26.4.0) - '@nanoforge-dev/common': - specifier: workspace:* - version: link:../../packages/common - '@nanoforge-dev/core': - specifier: workspace:* - version: link:../../packages/core - '@nanoforge-dev/ecs-client': - specifier: workspace:* - version: link:../../packages/ecs-client - '@nanoforge-dev/ecs-server': - specifier: workspace:* - version: link:../../packages/ecs-server - '@nanoforge-dev/graphics-2d': - specifier: workspace:* - version: link:../../packages/graphics-2d - '@nanoforge-dev/input': - specifier: workspace:* - version: link:../../packages/input - '@nanoforge-dev/music': - specifier: workspace:* - version: link:../../packages/music - '@nanoforge-dev/network-client': - specifier: workspace:* - version: link:../../packages/network-client - '@nanoforge-dev/network-server': - specifier: workspace:* - version: link:../../packages/network-server - '@nanoforge-dev/sound': - specifier: workspace:* - version: link:../../packages/sound - typescript: - specifier: catalog:core - version: 7.0.2 + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) example/pong-network: devDependencies: - '@nanoforge-dev/asset-manager': + '@nanoforge-dev/asset': specifier: workspace:* - version: link:../../packages/asset-manager + version: link:../../packages/asset '@nanoforge-dev/cli': specifier: latest version: 1.6.2(@types/node@26.4.0) '@nanoforge-dev/common': specifier: workspace:* version: link:../../packages/common - '@nanoforge-dev/config': - specifier: workspace:* - version: link:../../packages/config '@nanoforge-dev/core': specifier: workspace:* version: link:../../packages/core - '@nanoforge-dev/ecs-client': - specifier: workspace:* - version: link:../../packages/ecs-client - '@nanoforge-dev/ecs-server': - specifier: workspace:* - version: link:../../packages/ecs-server - '@nanoforge-dev/graphics-2d': - specifier: workspace:* - version: link:../../packages/graphics-2d - '@nanoforge-dev/input': - specifier: workspace:* - version: link:../../packages/input - '@nanoforge-dev/music': - specifier: workspace:* - version: link:../../packages/music - '@nanoforge-dev/network-client': - specifier: workspace:* - version: link:../../packages/network-client - '@nanoforge-dev/network-server': - specifier: workspace:* - version: link:../../packages/network-server - '@nanoforge-dev/sound': - specifier: workspace:* - version: link:../../packages/sound - '@nanoforge-dev/utils-eslint-config': - specifier: workspace:* - version: link:../../utils/eslint-config - '@nanoforge-dev/utils-prettier-config': + '@nanoforge-dev/env': specifier: workspace:* - version: link:../../utils/prettier-config + version: link:../../packages/env '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) @@ -267,190 +296,112 @@ importers: version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) lint-staged: specifier: catalog:ci - version: 17.3.0 + version: 17.4.1 prettier: specifier: catalog:lint version: 3.9.6 typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 + vitest: + specifier: catalog:test + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/asset-manager: - dependencies: + example/pong-network/apps/client: + devDependencies: + '@nanoforge-dev/asset': + specifier: workspace:* + version: link:../../../../packages/asset '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - devDependencies: - '@favware/cliff-jumper': - specifier: catalog:ci - version: 6.1.0 - '@nanoforge-dev/utils-eslint-config': + version: link:../../../../packages/common + '@nanoforge-dev/core': specifier: workspace:* - version: link:../../utils/eslint-config - '@nanoforge-dev/utils-prettier-config': + version: link:../../../../packages/core + '@nanoforge-dev/ecs': specifier: workspace:* - version: link:../../utils/prettier-config - '@trivago/prettier-plugin-sort-imports': - specifier: catalog:lint - version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) - eslint: - specifier: catalog:lint - version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - prettier: - specifier: catalog:lint - version: 3.9.6 - tsdown: - specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) - typescript: - specifier: catalog:core - version: 7.0.2 - unrun: - specifier: catalog:build - version: 0.3.1(synckit@0.11.13) - vitest: - specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - - packages/common: - devDependencies: - '@favware/cliff-jumper': - specifier: catalog:ci - version: 6.1.0 - '@nanoforge-dev/utils-eslint-config': + version: link:../../../../modules/ecs + '@nanoforge-dev/env': specifier: workspace:* - version: link:../../utils/eslint-config - '@nanoforge-dev/utils-prettier-config': + version: link:../../../../packages/env + '@nanoforge-dev/graphics-2d': specifier: workspace:* - version: link:../../utils/prettier-config - '@trivago/prettier-plugin-sort-imports': - specifier: catalog:lint - version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) - eslint: - specifier: catalog:lint - version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - prettier: - specifier: catalog:lint - version: 3.9.6 - tsdown: - specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) - typescript: - specifier: catalog:core - version: 7.0.2 - unrun: - specifier: catalog:build - version: 0.3.1(synckit@0.11.13) - vitest: - specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - - packages/config: - dependencies: - class-transformer: - specifier: catalog:config - version: 0.5.1 - class-validator: - specifier: catalog:config - version: 0.14.4 - devDependencies: - '@favware/cliff-jumper': - specifier: catalog:ci - version: 6.1.0 + version: link:../../../../modules/graphics-2d + '@nanoforge-dev/input': + specifier: workspace:* + version: link:../../../../modules/input + '@nanoforge-dev/network': + specifier: workspace:* + version: link:../../../../modules/network '@nanoforge-dev/utils-eslint-config': specifier: workspace:* - version: link:../../utils/eslint-config + version: link:../../../../utils/eslint-config '@nanoforge-dev/utils-prettier-config': specifier: workspace:* - version: link:../../utils/prettier-config + version: link:../../../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + lint-staged: + specifier: catalog:ci + version: 17.4.1 prettier: specifier: catalog:lint version: 3.9.6 - tsdown: - specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 - unrun: - specifier: catalog:build - version: 0.3.1(synckit@0.11.13) + version: 6.0.3 - packages/core: - dependencies: - '@nanoforge-dev/asset-manager': + example/pong-network/apps/server: + devDependencies: + '@nanoforge-dev/asset': specifier: workspace:* - version: link:../asset-manager + version: link:../../../../packages/asset '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - '@nanoforge-dev/input': + version: link:../../../../packages/common + '@nanoforge-dev/core': specifier: workspace:* - version: link:../input - class-transformer: - specifier: catalog:config - version: 0.5.1 - class-validator: - specifier: catalog:config - version: 0.14.4 - devDependencies: - '@favware/cliff-jumper': - specifier: catalog:ci - version: 6.1.0 + version: link:../../../../packages/core + '@nanoforge-dev/ecs': + specifier: workspace:* + version: link:../../../../modules/ecs + '@nanoforge-dev/env': + specifier: workspace:* + version: link:../../../../packages/env + '@nanoforge-dev/network': + specifier: workspace:* + version: link:../../../../modules/network '@nanoforge-dev/utils-eslint-config': specifier: workspace:* - version: link:../../utils/eslint-config + version: link:../../../../utils/eslint-config '@nanoforge-dev/utils-prettier-config': specifier: workspace:* - version: link:../../utils/prettier-config + version: link:../../../../utils/prettier-config '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) + lint-staged: + specifier: catalog:ci + version: 17.4.1 prettier: specifier: catalog:lint version: 3.9.6 - tsdown: - specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 - unrun: - specifier: catalog:build - version: 0.3.1(synckit@0.11.13) - vitest: - specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 6.0.3 - packages/core-editor: + modules/ecs: dependencies: - '@nanoforge-dev/asset-manager': - specifier: workspace:* - version: link:../asset-manager '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - '@nanoforge-dev/ecs-client': - specifier: workspace:* - version: link:../ecs-client - '@nanoforge-dev/input': - specifier: workspace:* - version: link:../input - class-transformer: - specifier: catalog:config - version: 0.5.1 - class-validator: - specifier: catalog:config - version: 0.14.4 + version: link:../../packages/common devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -472,35 +423,29 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/ecs-client: + modules/editor: dependencies: '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - '@nanoforge-dev/ecs-lib': - specifier: workspace:* - version: link:../ecs-lib + version: link:../../packages/common devDependencies: '@favware/cliff-jumper': specifier: catalog:ci version: 6.1.0 - '@nanoforge-dev/asset-manager': - specifier: workspace:* - version: link:../asset-manager '@nanoforge-dev/core': specifier: workspace:* - version: link:../core + version: link:../../packages/core '@nanoforge-dev/utils-eslint-config': specifier: workspace:* version: link:../../utils/eslint-config @@ -510,9 +455,6 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) - '@types/node': - specifier: catalog:core - version: 26.4.0 eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) @@ -521,26 +463,35 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/ecs-lib: + modules/graphics-2d: dependencies: '@nanoforge-dev/common': specifier: workspace:* - version: link:../common + version: link:../../packages/common + konva: + specifier: catalog:graphics + version: 10.3.2 devDependencies: '@favware/cliff-jumper': specifier: catalog:ci version: 6.1.0 + '@nanoforge-dev/ecs': + specifier: workspace:* + version: link:../ecs + '@nanoforge-dev/editor-lib': + specifier: workspace:* + version: link:../editor '@nanoforge-dev/utils-eslint-config': specifier: workspace:* version: link:../../utils/eslint-config @@ -550,9 +501,6 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) - '@types/node': - specifier: catalog:core - version: 26.4.0 eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) @@ -561,35 +509,26 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/ecs-server: + modules/input: dependencies: '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - '@nanoforge-dev/ecs-lib': - specifier: workspace:* - version: link:../ecs-lib + version: link:../../packages/common devDependencies: '@favware/cliff-jumper': specifier: catalog:ci version: 6.1.0 - '@nanoforge-dev/asset-manager': - specifier: workspace:* - version: link:../asset-manager - '@nanoforge-dev/core': - specifier: workspace:* - version: link:../core '@nanoforge-dev/utils-eslint-config': specifier: workspace:* version: link:../../utils/eslint-config @@ -599,9 +538,6 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) - '@types/node': - specifier: catalog:core - version: 26.4.0 eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) @@ -610,25 +546,22 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/graphics-2d: + modules/music: dependencies: '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - konva: - specifier: catalog:graphics - version: 10.3.0 + version: link:../../packages/common devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -650,28 +583,34 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/graphics-2d-editor: + modules/network: dependencies: + '@mapbox/node-pre-gyp': + specifier: catalog:network + version: 2.0.3(supports-color@10.2.2) '@nanoforge-dev/common': specifier: workspace:* - version: link:../common - '@nanoforge-dev/core-editor': - specifier: workspace:* - version: link:../core-editor - '@nanoforge-dev/ecs-lib': + version: link:../../packages/common + '@nanoforge-dev/env': specifier: workspace:* - version: link:../ecs-lib + version: link:../../packages/env + wrtc: + specifier: catalog:network + version: 0.4.7 + ws: + specifier: catalog:network + version: 8.21.3 devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -685,6 +624,9 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) + '@types/ws': + specifier: catalog:network + version: 8.18.1 eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) @@ -693,22 +635,22 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/input: + modules/sound: dependencies: '@nanoforge-dev/common': specifier: workspace:* - version: link:../common + version: link:../../packages/common devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -730,18 +672,18 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/music: + packages/asset: dependencies: '@nanoforge-dev/common': specifier: workspace:* @@ -767,25 +709,18 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/network-client: - dependencies: - '@nanoforge-dev/common': - specifier: workspace:* - version: link:../common - '@nanoforge-dev/config': - specifier: workspace:* - version: link:../config + packages/common: devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -807,34 +742,25 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/network-server: + packages/core: dependencies: - '@mapbox/node-pre-gyp': - specifier: catalog:network - version: 2.0.3(supports-color@10.2.2) + '@nanoforge-dev/asset': + specifier: workspace:* + version: link:../asset '@nanoforge-dev/common': specifier: workspace:* version: link:../common - '@nanoforge-dev/config': - specifier: workspace:* - version: link:../config - wrtc: - specifier: catalog:network - version: 0.4.7 - ws: - specifier: catalog:network - version: 8.21.0 devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -848,9 +774,6 @@ importers: '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) - '@types/ws': - specifier: catalog:network - version: 8.18.1 eslint: specifier: catalog:lint version: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) @@ -859,22 +782,28 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) - packages/sound: + packages/env: dependencies: '@nanoforge-dev/common': specifier: workspace:* version: link:../common + class-transformer: + specifier: catalog:config + version: 0.5.1 + class-validator: + specifier: catalog:config + version: 0.14.4 devDependencies: '@favware/cliff-jumper': specifier: catalog:ci @@ -896,16 +825,16 @@ importers: version: 3.9.6 tsdown: specifier: catalog:build - version: 0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)) + version: 0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)) typescript: specifier: catalog:core - version: 7.0.2 + version: 6.0.3 unrun: specifier: catalog:build version: 0.3.1(synckit@0.11.13) vitest: specifier: catalog:test - version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + version: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) utils/eslint-config: dependencies: @@ -929,10 +858,10 @@ importers: version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(prettier@3.9.6) globals: specifier: catalog:lint - version: 17.7.0 + version: 17.11.0 typescript-eslint: specifier: catalog:lint - version: 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + version: 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) devDependencies: '@nanoforge-dev/utils-prettier-config': specifier: workspace:* @@ -1154,15 +1083,6 @@ packages: '@dprint/toml@0.7.0': resolution: {integrity: sha512-eFaQTcfxKHB+YyTh83x7GEv+gDPuj9q5NFOTaoj5rZmQTbj6OgjjMxUicmS1R8zYcx8YAq5oA9J3YFa5U6x2gA==} - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - - '@emnapi/wasi-threads@1.2.2': - resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - '@eslint-community/eslint-utils@4.10.1': resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1242,8 +1162,8 @@ packages: resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/checkbox@5.2.1': - resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} + '@inquirer/checkbox@5.2.3': + resolution: {integrity: sha512-XEYX2WA8SBkLPczL6/yXPHLPCvDoptmh9v56Cy05BSV1Smk1vWy19bTC4qJBuIffw7+6l4CcaYYzGqG60RfW1g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1251,8 +1171,8 @@ packages: '@types/node': optional: true - '@inquirer/confirm@6.1.1': - resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} + '@inquirer/confirm@6.3.0': + resolution: {integrity: sha512-pZHXJImFtERmSNMBHcjwuz8Ck5vEFEYNUZnwbb8aJpjHv/TwGuFErNxF2Hp8+V+pNJs2EYPMlyWscvFEqO9jOQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1260,8 +1180,8 @@ packages: '@types/node': optional: true - '@inquirer/core@11.2.1': - resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} + '@inquirer/core@12.0.1': + resolution: {integrity: sha512-JMD5Jy/ScL5TZE18m83Nw25HjqGFLoWXwnEkW7IdwwAhZpB9Bus55/WU7zn3UqR1MOCjjTQOIYpiD4vjWA3LPw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1269,8 +1189,8 @@ packages: '@types/node': optional: true - '@inquirer/editor@5.2.2': - resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} + '@inquirer/editor@5.3.1': + resolution: {integrity: sha512-y43COoyVUjPWIobn2Qep/uI1drPS78aaZZZ9kVi94Tyu/GuW2N8d8Q4rifJXGAXCEAXCPTTMjD8gC1HyvM5ukA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1278,8 +1198,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@5.1.1': - resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} + '@inquirer/expand@5.1.3': + resolution: {integrity: sha512-3NQJiXNJ/aj9wiAsr7pECdp5Qe9J0X9YUJCKsaFXS+ddOxfL6J4AIl3w3T4Gq3kK0WsQY5GMoDokK5X94m6lHw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1287,8 +1207,8 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@3.0.3': - resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} + '@inquirer/external-editor@3.0.4': + resolution: {integrity: sha512-tZbbaK2ovq6vlrRBNQvjrypmrED/p5x2ncIHQ79cD55tei3dD96v5glMMA+6tiq7K104i/25DVYKWVPJuV6ptA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1296,12 +1216,12 @@ packages: '@types/node': optional: true - '@inquirer/figures@2.0.7': - resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} + '@inquirer/figures@2.0.8': + resolution: {integrity: sha512-tApbon79GM9ry56ja/Ud3SY2CL4TQsao9fIwDQbgTeNY55025GdMzQ2+UdegV/lx51VNGUB59M0v0nMpybYY4Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} - '@inquirer/input@5.1.2': - resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} + '@inquirer/input@5.1.4': + resolution: {integrity: sha512-3xQkQrOvgOzpSN2ciTVdRDlg1FWMCA8l+0KfB6SNlILoTCGzJTzO/gc0Rwjcb3usuGyKdaGtI6OiyMdeMeLWkg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1309,8 +1229,8 @@ packages: '@types/node': optional: true - '@inquirer/number@4.1.1': - resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} + '@inquirer/number@4.2.1': + resolution: {integrity: sha512-5KaqwZNLRpUuWcoCrYghPP9TMaXL5v2Sk4xqePM7RCVegcJStoXdWibio60YIC1bec+z1fCyb67N6XPJIkZtGA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1318,8 +1238,8 @@ packages: '@types/node': optional: true - '@inquirer/password@5.1.1': - resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} + '@inquirer/password@5.2.0': + resolution: {integrity: sha512-CvVcW09emkBESEOW+4R8CjLNkP3fB3XrjeL8CDvfpjgrJN+V9oerXmJAXXM3l+4xqYPD5Yaujzy/Ph0PLOdDuA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1336,8 +1256,17 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@5.3.1': - resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} + '@inquirer/prompts@8.7.0': + resolution: {integrity: sha512-yQwBMYvpJ6jqrXtKiOwRD5XezjJoyt3VQvIyjsr5Arqb519nfIohOQymWVJ8/vEgg8xtZerrCsqlSaqt/LPC9A==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@5.3.3': + resolution: {integrity: sha512-Mu7WrtmDLaXBDEyrRLS70SZgX9ZSm4Up1w0ZxiH8C1OOp9oaVCn2k8q3QGgmlnhsKYUhuaU3zFWhAP6wxkVIMA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1345,8 +1274,8 @@ packages: '@types/node': optional: true - '@inquirer/search@4.2.1': - resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} + '@inquirer/search@4.3.1': + resolution: {integrity: sha512-0VWOvsHWI0rPj6CG70MoP4oXNCB6adcyN8bVFZXnh11eLDdPIK2f2XCmva78acPPDfJisfab7qNakwBh7hdBXw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1354,8 +1283,8 @@ packages: '@types/node': optional: true - '@inquirer/select@5.2.1': - resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} + '@inquirer/select@5.2.3': + resolution: {integrity: sha512-KuRTodDa6xBXX2noIpjuitpX/QT7Sfav7dIZ/OfUY54Hxg95nrGoshSzxx6Ey7qqLbImKdiGkSDt7KjPXjQgmA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1363,8 +1292,8 @@ packages: '@types/node': optional: true - '@inquirer/type@4.0.7': - resolution: {integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==} + '@inquirer/type@4.1.0': + resolution: {integrity: sha512-FMiJpuHUG3Dk0ex+UIXkre7i+i4OcwHWk9YdcVtZHFwb/r2rnrU2ipTCNAB7A+QOP0ryzIcqOfy76fRyyvOEAw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -1383,8 +1312,8 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} @@ -1445,37 +1374,18 @@ packages: resolution: {integrity: sha512-MdmhFncakgejGRIf1HTPKTskhdv8bIst21uWRSZCXGgGv0UNYEfDiziOsWPVCzGc9dXei59RIDznBwgpAMeXLg==} engines: {node: '25'} - '@napi-rs/wasm-runtime@1.2.3': - resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} - engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} - peerDependencies: - '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 - '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 - '@octokit/auth-token@6.0.0': resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} engines: {node: '>= 20'} - '@octokit/core@7.0.6': - resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} - engines: {node: '>= 20'} - '@octokit/core@7.0.7': resolution: {integrity: sha512-DcB0M3KFgr9ECI328lhBMVsyFT2DnmNucSBTqEN3exyNKUzkkpUSCHmTRcunF41Eou2TIQKW4seewri8ON9bSA==} engines: {node: '>= 20'} - '@octokit/endpoint@11.0.3': - resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} - engines: {node: '>= 20'} - '@octokit/endpoint@11.0.4': resolution: {integrity: sha512-f1cOWoHPmxryJFknxbtDdjODWfV8A9tc8Aae6ermXPNgHFZ/x91AtHIz4gicEjL8hkJiip+u21QHJORfBv/qiA==} engines: {node: '>= 20'} - '@octokit/graphql@9.0.3': - resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==} - engines: {node: '>= 20'} - '@octokit/graphql@9.0.4': resolution: {integrity: sha512-5s15CCiY8XXQ+FG+b1YQcl6Z2FA++nwAz/tg2VUrTmnMncP+2nnGUEYANImdnxsA2Fnq+Mbl7hDjUTw7cFAwcg==} engines: {node: '>= 20'} @@ -1498,24 +1408,16 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/plugin-retry@8.1.0': - resolution: {integrity: sha512-O1FZgXeiGb2sowEr/hYTr6YunGdSAFWnr2fyW39Ah85H8O33ELASQxcvOFF5LE6Tjekcyu2ms4qAzJVhSaJxTw==} + '@octokit/plugin-retry@8.1.1': + resolution: {integrity: sha512-VCVvZ/R1+u3WuiBWpNavZ0mY4aaJNAsENrpBP9aLSR2QyOpQgd7DhM5j4AW7z4MQpnJYgwBPf0XqPQoNBRdQwg==} engines: {node: '>= 20'} peerDependencies: '@octokit/core': '>=7' - '@octokit/request-error@7.1.0': - resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} - engines: {node: '>= 20'} - '@octokit/request-error@7.1.1': resolution: {integrity: sha512-+eaY7G2VVpSf2pc5Gn1+mph837V/d/TYTJAgWL9Tb0ogGYcpN3IlAVFgjL+Vv93F/sevrxkvsYCedtpLdcFLzA==} engines: {node: '>= 20'} - '@octokit/request@10.0.10': - resolution: {integrity: sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w==} - engines: {node: '>= 20'} - '@octokit/request@10.0.15': resolution: {integrity: sha512-3CBg9aJ0hO9Pjyij8LbK/xYtEaPws9SW7xKz67daPNxQB1q5Y9OMA7DDOG0A6Hwf9ygGu3tvzusg0LXQ8/wAjA==} engines: {node: '>= 20'} @@ -1526,89 +1428,70 @@ packages: '@octokit/types@17.0.0': resolution: {integrity: sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==} - '@oven/bun-darwin-aarch64@1.3.14': - resolution: {integrity: sha512-Omj20SuiHBOUjUBIyqtkNjSUIjOtEOJwmbix/ZyFH4BaQ6OZTaaRWIR4TjHVz0yadHgli6lLTiAh1uarnvD49A==} + '@oven/bun-darwin-aarch64@1.4.0': + resolution: {integrity: sha512-GCpf8QuFLsyioVawP5HrMxA1ZRBlu6Hq9RNnSc3UTUWAzIxBso9trjoZczw1HdgpqSssFkszfIV2zmOzFTjhkw==} cpu: [arm64] os: [darwin] - '@oven/bun-darwin-x64-baseline@1.3.14': - resolution: {integrity: sha512-OSfsTZstc898HHElhU4NccaBGOSSDn5VfahiVTnidZ9B/+wb7WTyfZJaBeJcfjwJ9H2W9uTh2TGtl3UfcXgV9g==} - cpu: [x64] - os: [darwin] - - '@oven/bun-darwin-x64@1.3.14': - resolution: {integrity: sha512-FFj3QdU/OhlDyZOJ8CWfN5eWLpRlT4qjZg7lMQi7jA6GuoY5ajlO1zWLP/MuHYRSbXQUvV52RejNi8DVnAp13w==} + '@oven/bun-darwin-x64@1.4.0': + resolution: {integrity: sha512-cIrhwOr0SPEraewznhC+c/k6TG8bwFn5uZ4EJuXwjiKJLcAF36q7/bGjWkeXSe48JwMcPRUR054JXF7+cRwSSA==} cpu: [x64] os: [darwin] - '@oven/bun-freebsd-aarch64@1.3.14': - resolution: {integrity: sha512-LIKrXaFxAHybVO5Pf+9XP2FHUj/5APvXTUKk9dqHm5iFz4oH+W24cmhjkJirNujh9hKeTyrpWSe3no9JZKowIw==} + '@oven/bun-freebsd-aarch64@1.4.0': + resolution: {integrity: sha512-09x7wnjMR6M5KGBDBhVl2CpfoCIQOkVDbPX2KfIhpXv4N6grbWE7dfLPw/Ydi9gaUMGhU7UKhoz444Nu6RCycA==} cpu: [arm64] os: [freebsd] - '@oven/bun-freebsd-x64@1.3.14': - resolution: {integrity: sha512-uwD+fGUH1ADpIF3B1U2jWzzb20QwRLZfj5QZ28GUCGrAJ/nTmWrD6YYGsblCY1wuhldRez3lU40AyuvSCyLYmw==} + '@oven/bun-freebsd-x64@1.4.0': + resolution: {integrity: sha512-dRwzti/qJqV1HWplU27iUWUqp+f2DtFSf2yqQKSb+HH2dDOC//Uqd9u/A5h1DMsLszfP5OGP9UwQIKxVwFODaA==} cpu: [x64] os: [freebsd] - '@oven/bun-linux-aarch64-android@1.3.14': - resolution: {integrity: sha512-y4kq5b85lsrmFb9Xvi4w9mA5IEFJkLMrSmYn06q24KjL9rUWDWO3VFZEtteZxUN5+ec3Zm5S8OnJw1umaCbVjA==} + '@oven/bun-linux-aarch64-android@1.4.0': + resolution: {integrity: sha512-HpPIxJfDNPBPhiBNMyZoo/dOLijARfsx5j72vNuLtaTvl0Hh7HUculxjsOQ2WSyGoCgqXMEr1Qqjab1im9u1RA==} cpu: [arm64] os: [android] - '@oven/bun-linux-aarch64-musl@1.3.14': - resolution: {integrity: sha512-jmqOA92Cd1NL/1XBd4bFkJLxQ86K0RW7ohxS2qzzAvuitO4JiIxjjTeCspoU44zCozH72HpfZfUE2On31OjnWA==} + '@oven/bun-linux-aarch64-musl@1.4.0': + resolution: {integrity: sha512-RUjAAkJ/CdNV++zVxyANWshPc73CECYsfhk0fWAkoJjtywxJ2BwXzI6nopBBDMfs0HS+fhRGn6zGwU8ccxLeJg==} cpu: [arm64] os: [linux] + libc: [musl] - '@oven/bun-linux-aarch64@1.3.14': - resolution: {integrity: sha512-X5SsPZHs+iYO8R/efIcRtc7gT2Q2DgPfliCxEkx4cXBumwkw0c/EsHMNwH3EgGpCDaZ7IYVPhpCG/xBOQHEwZw==} + '@oven/bun-linux-aarch64@1.4.0': + resolution: {integrity: sha512-Y5yAtCbHK6JjprXEtkdklDQFPADgs+CkfcliyY5g4JJ8baGHyQSrfpSkX3XVJ2C+aBLsdwNDdW+oczMsAwx6uA==} cpu: [arm64] os: [linux] + libc: [glibc] - '@oven/bun-linux-x64-android@1.3.14': - resolution: {integrity: sha512-qe9e1d+3VAEU7nAA2ol9Jvmy/o99PVMSgZhHn7Q/9O3YcDrfEqyQ8zm4zoe5qTEo8HZH0dN03Le0Ys2eQPs7eg==} + '@oven/bun-linux-x64-android@1.4.0': + resolution: {integrity: sha512-u++KyLlfMn36yWz+AgJs+fZtS46UFDNpSSZhrcitkytONtNwq0X6Q9BDVEFXxYl/+Eec0xme1rb6MgW+U35WeA==} cpu: [x64] os: [android] - '@oven/bun-linux-x64-baseline@1.3.14': - resolution: {integrity: sha512-q/8EdOC0yUE8FPeoOVq8/Pw5I9/tJaYmUfO/uDUAREx8IUnOJH1RJ5A3BjFqre8pvJoiZA9AovPJq5FnNNjSxA==} - cpu: [x64] - os: [linux] - - '@oven/bun-linux-x64-musl-baseline@1.3.14': - resolution: {integrity: sha512-n6iE71G4lQE4XkrZhQQcL5YUlxDbnq6nqV7zeQi33PMsLT/0kYE+RvHOtBWZ3w0wMdXZfINmp63hIb9ijUBGtw==} - cpu: [x64] - os: [linux] - - '@oven/bun-linux-x64-musl@1.3.14': - resolution: {integrity: sha512-GBCB/k/sIqcr06eTNgg7g46qiUv35Jasx4XiccJ/n7RGqrE4RWUD/XJBbWFprVPjvqd59+QtSnS99XGqvftHfg==} + '@oven/bun-linux-x64-musl@1.4.0': + resolution: {integrity: sha512-C1Dv+ISL8YKEKM9jAHzNifOcRUoziy6UMxh+yVXjUCP6QnbRhENDHLaIWWkQZJyBLTn0I3xozflorAlHiGzGqA==} cpu: [x64] os: [linux] + libc: [musl] - '@oven/bun-linux-x64@1.3.14': - resolution: {integrity: sha512-7OVTAKvwfPmSbIV1HpdOoVVx5VRc427GuPPne93N6vk4eQBPId9nXmZDh9/zGaKPdbVjVtQSZafWQoUjx38Utw==} + '@oven/bun-linux-x64@1.4.0': + resolution: {integrity: sha512-Du44zebtPXJujvMLmtIxEQ6ykOhYt7L/Q+YIGVm+Yy+Pj/fpOnq60ggwIpKp/pGAFbYHNiTrA3JTjuZ9MTbZIg==} cpu: [x64] os: [linux] + libc: [glibc] - '@oven/bun-windows-aarch64@1.3.14': - resolution: {integrity: sha512-T7s3x/BsVKQObGU6QDkZeI6wKynzqGbBH1yI77jrrj5siElclxr3DQrDIk8CV4G5/SJq2HHq4kpLyYY2DKCSmA==} + '@oven/bun-windows-aarch64@1.4.0': + resolution: {integrity: sha512-FBAYaQpJBP0asgqzL6NFUfjdQqsV+kvTpJ/eWxPKj+RcDgIfPSuE8kvQuPYu5pa8u8JTujYMjmuyvHxVuQsInA==} cpu: [arm64] os: [win32] - '@oven/bun-windows-x64-baseline@1.3.14': - resolution: {integrity: sha512-uIjLUC1S9DWgICzuoMba7vurBJnBruE4S5CxnvmZkdqWVXRzx1Rgu636HoH+k0qeaQCFh3jeG3JQ1y6fRHv0sw==} - cpu: [x64] - os: [win32] - - '@oven/bun-windows-x64@1.3.14': - resolution: {integrity: sha512-mUFWL3BoYkNpjd8e9PqROiFF/1Xeotq20mABJsiQH62jM1g5zqWh4khw1RZ6bX8Q8fWvlPaxG1PjofkmjUi3vg==} + '@oven/bun-windows-x64@1.4.0': + resolution: {integrity: sha512-jRKv1NPLznMSZY5BEWciMF7zv0Tiyo2pQSxAJ3w+YWJ6y3VWNJQQQdLlV5Jx8lbOFDrJdrc9dD3GV17k3BP41A==} cpu: [x64] os: [win32] - '@oxc-project/types@0.139.0': - resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} - '@oxc-project/types@0.147.0': resolution: {integrity: sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==} @@ -1747,73 +1630,36 @@ packages: cpu: [arm] os: [android] - '@rolldown/binding-android-arm64@1.1.5': - resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - '@rolldown/binding-android-arm64@1.2.6': resolution: {integrity: sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.5': - resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - '@rolldown/binding-darwin-arm64@1.2.6': resolution: {integrity: sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.5': - resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - '@rolldown/binding-darwin-x64@1.2.6': resolution: {integrity: sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.5': - resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - '@rolldown/binding-freebsd-x64@1.2.6': resolution: {integrity: sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': - resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.2.6': resolution: {integrity: sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.5': - resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-arm64-gnu@1.2.6': resolution: {integrity: sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1821,13 +1667,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.1.5': - resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - '@rolldown/binding-linux-arm64-musl@1.2.6': resolution: {integrity: sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1835,13 +1674,6 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.1.5': - resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-ppc64-gnu@1.2.6': resolution: {integrity: sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1849,24 +1681,10 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.1.5': - resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.2.6': resolution: {integrity: sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==} engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-x64-gnu@1.1.5': - resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] + cpu: [s390x] os: [linux] libc: [glibc] @@ -1877,13 +1695,6 @@ packages: os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.1.5': - resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - '@rolldown/binding-linux-x64-musl@1.2.6': resolution: {integrity: sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1891,41 +1702,18 @@ packages: os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.1.5': - resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.2.6': resolution: {integrity: sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.5': - resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.1.5': - resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.2.6': resolution: {integrity: sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.5': - resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - '@rolldown/binding-win32-x64-msvc@1.2.6': resolution: {integrity: sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2088,9 +1876,6 @@ packages: cpu: [arm64] os: [win32] - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} - '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} @@ -2121,185 +1906,65 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@typescript-eslint/eslint-plugin@8.62.0': - resolution: {integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==} + '@typescript-eslint/eslint-plugin@8.68.0': + resolution: {integrity: sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.62.0 + '@typescript-eslint/parser': ^8.68.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.62.0': - resolution: {integrity: sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==} + '@typescript-eslint/parser@8.68.0': + resolution: {integrity: sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.62.0': - resolution: {integrity: sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==} + '@typescript-eslint/project-service@8.68.0': + resolution: {integrity: sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.62.0': - resolution: {integrity: sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==} + '@typescript-eslint/scope-manager@8.68.0': + resolution: {integrity: sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.62.0': - resolution: {integrity: sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==} + '@typescript-eslint/tsconfig-utils@8.68.0': + resolution: {integrity: sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.62.0': - resolution: {integrity: sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==} + '@typescript-eslint/type-utils@8.68.0': + resolution: {integrity: sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.62.0': - resolution: {integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==} + '@typescript-eslint/types@8.68.0': + resolution: {integrity: sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.62.0': - resolution: {integrity: sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==} + '@typescript-eslint/typescript-estree@8.68.0': + resolution: {integrity: sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.62.0': - resolution: {integrity: sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==} + '@typescript-eslint/utils@8.68.0': + resolution: {integrity: sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.62.0': - resolution: {integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==} + '@typescript-eslint/visitor-keys@8.68.0': + resolution: {integrity: sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript/typescript-aix-ppc64@7.0.2': - resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} - engines: {node: '>=16.20.0'} - cpu: [ppc64] - os: [aix] - - '@typescript/typescript-darwin-arm64@7.0.2': - resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [darwin] - - '@typescript/typescript-darwin-x64@7.0.2': - resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [darwin] - - '@typescript/typescript-freebsd-arm64@7.0.2': - resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [freebsd] - - '@typescript/typescript-freebsd-x64@7.0.2': - resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [freebsd] - - '@typescript/typescript-linux-arm64@7.0.2': - resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [linux] - - '@typescript/typescript-linux-arm@7.0.2': - resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} - engines: {node: '>=16.20.0'} - cpu: [arm] - os: [linux] - - '@typescript/typescript-linux-loong64@7.0.2': - resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} - engines: {node: '>=16.20.0'} - cpu: [loong64] - os: [linux] - - '@typescript/typescript-linux-mips64el@7.0.2': - resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} - engines: {node: '>=16.20.0'} - cpu: [mips64el] - os: [linux] - - '@typescript/typescript-linux-ppc64@7.0.2': - resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} - engines: {node: '>=16.20.0'} - cpu: [ppc64] - os: [linux] - - '@typescript/typescript-linux-riscv64@7.0.2': - resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} - engines: {node: '>=16.20.0'} - cpu: [riscv64] - os: [linux] - - '@typescript/typescript-linux-s390x@7.0.2': - resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} - engines: {node: '>=16.20.0'} - cpu: [s390x] - os: [linux] - - '@typescript/typescript-linux-x64@7.0.2': - resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [linux] - - '@typescript/typescript-netbsd-arm64@7.0.2': - resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [netbsd] - - '@typescript/typescript-netbsd-x64@7.0.2': - resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [netbsd] - - '@typescript/typescript-openbsd-arm64@7.0.2': - resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [openbsd] - - '@typescript/typescript-openbsd-x64@7.0.2': - resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [openbsd] - - '@typescript/typescript-sunos-x64@7.0.2': - resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [sunos] - - '@typescript/typescript-win32-arm64@7.0.2': - resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [win32] - - '@typescript/typescript-win32-x64@7.0.2': - resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [win32] - '@vitest/coverage-v8@4.1.11': resolution: {integrity: sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==} peerDependencies: @@ -2527,8 +2192,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} engines: {node: '>=12'} ansi-styles@6.2.3: @@ -2590,8 +2255,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - bun@1.3.14: - resolution: {integrity: sha512-aB6GVd42x1Y5ie1K16SF+oLGtgSkwX9hgoDdIW88pjvfTccU8F1vfpoOt34QLv0dZ1v3XimtaxPlZUG81Gx9Zg==} + bun@1.4.0: + resolution: {integrity: sha512-iRiFkc2W7UVpCyZXO9tod45TP9QCyN19fWqbpeN/jaM/K7uzeHYx/OSPsahMJazGKBgPsnxRt+4Jc43d8BcHZw==} cpu: [arm64, x64] os: [darwin, linux, android, freebsd, win32] hasBin: true @@ -2702,10 +2367,6 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - content-type@2.0.0: - resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} - engines: {node: '>=18'} - content-type@3.0.0: resolution: {integrity: sha512-AIi5H6p0xk5uknXcN3/rmhP8jgp69OfSe/JuKiQAFprJ7UGw7mwj7m4XcmDzlrnJDG+cGpphAINGdU3g3g7kDw==} engines: {node: '>=22'} @@ -2781,8 +2442,8 @@ packages: resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} engines: {node: '>=18'} - default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + default-browser@5.5.1: + resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==} engines: {node: '>=18'} define-data-property@1.1.4: @@ -2876,8 +2537,8 @@ packages: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} - es-toolkit@1.51.0: - resolution: {integrity: sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==} + es-toolkit@1.52.0: + resolution: {integrity: sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==} escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} @@ -3126,8 +2787,8 @@ packages: resolution: {integrity: sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==} engines: {node: '>=20'} - globals@17.7.0: - resolution: {integrity: sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==} + globals@17.11.0: + resolution: {integrity: sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==} engines: {node: '>=18'} gopd@1.2.0: @@ -3179,16 +2840,16 @@ packages: engines: {node: '>=18'} hasBin: true - iconv-lite@0.7.2: - resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} engines: {node: '>= 4'} import-fresh@3.3.1: @@ -3339,10 +3000,6 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} - hasBin: true - js-yaml@4.3.2: resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true @@ -3370,9 +3027,6 @@ packages: json-with-bigint@3.5.12: resolution: {integrity: sha512-uwbF/wSSuOgC7qqlq27Xp5B6a2MHVug3t0idZdTqu0JnlFvgJuH7ju+KAk/J06C7GfhoYy2gnb9wz2INqcne7w==} - json-with-bigint@3.5.8: - resolution: {integrity: sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==} - jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} @@ -3382,15 +3036,23 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - konva@10.3.0: - resolution: {integrity: sha512-gt19K2gzY4lHbnkvsku7eSmB+A9PTS2jG4F9coBMsdjM1UKfJNxJbDbXVpeCW1wjEGRwBD3nBamcHnqJhAeKlg==} + konva@10.3.2: + resolution: {integrity: sha512-A9GLx+Vj0PNnybjNq/St/S8utrksuSKOR8EzO2RTjA0SlmR9JipahcCXWW0vXz/9wjZCwAEtBtJFCUGe5mD/4g==} + peerDependencies: + canvas: ^3.0.0 + skia-canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + skia-canvas: + optional: true levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - libphonenumber-js@1.13.7: - resolution: {integrity: sha512-rvr3HIMdOgzhz1RFGjftji+wjoAFlzhqCNqJOU/MKTZQ8d9NZxAR/tI+0weDicyoucqVR0U1GCniqHJ0f8aM2A==} + libphonenumber-js@1.13.12: + resolution: {integrity: sha512-uLVeV1c9OTk6qkdqnj+mpMD+ZdnZ0szVyWu58HwMmpwkHA1gCEkyjd3veZQXDnuw9KEwSRjcc9B1pS9XKIN1fA==} lightningcss-android-arm64@1.33.0: resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} @@ -3469,8 +3131,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@17.3.0: - resolution: {integrity: sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw==} + lint-staged@17.4.1: + resolution: {integrity: sha512-FmJeudcalbSfg1du+JCfvi5vS6Qt08KgbfLWiHinbef+2JJwUZwAWVoaO1AcJVUTWPfk0t30PMQNwPAeCzYQ+Q==} engines: {node: '>=22.22.1'} hasBin: true @@ -3623,15 +3285,15 @@ packages: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} - ohash@2.0.11: - resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + ohash@2.0.12: + resolution: {integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==} onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - open@11.0.0: - resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} + open@11.0.1: + resolution: {integrity: sha512-NzwMUB6C1D0+Kd+9iMS/H4k+Ck3cTX6Ckyfr/gAGlmvSE1LUQZnEZvWBi4PYmMwH/S5SMeTXnE+9uAz8uF+pWw==} engines: {node: '>=20'} optionator@0.9.4: @@ -3722,6 +3384,10 @@ packages: resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} engines: {node: '>=20'} + powershell-utils@0.2.0: + resolution: {integrity: sha512-ZlsFlG7MtSFCoc5xreOvBAozCJ6Pf06opgJjh9ONEv418xpZSAzNjstD36C6+JwOnfSqOW/9uDkqKjezTdxZhw==} + engines: {node: '>=20'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -3735,8 +3401,8 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-ms@9.3.0: - resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + pretty-ms@9.3.1: + resolution: {integrity: sha512-HzMy3Geq23nVALD/M2LliU+F+M+gVNsvkQWWqeBZ8HDiCgzo6YPJ/Omrmtq24EFrIsk0a3EkQGEd7bDOo+IhGA==} engines: {node: '>=18'} punycode@2.3.1: @@ -3758,8 +3424,8 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} reflect-metadata@0.2.2: @@ -3808,11 +3474,6 @@ packages: vue-tsc: optional: true - rolldown@1.1.5: - resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - rolldown@1.2.6: resolution: {integrity: sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3876,8 +3537,8 @@ packages: resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} engines: {node: '>=8'} - smol-toml@1.7.0: - resolution: {integrity: sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==} + smol-toml@1.8.0: + resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} engines: {node: '>= 18'} source-map-js@1.2.1: @@ -3917,10 +3578,6 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.2.1: - resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} - engines: {node: '>=20'} - string-width@8.2.2: resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} engines: {node: '>=20'} @@ -3961,8 +3618,8 @@ packages: resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} - tar@7.5.19: - resolution: {integrity: sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==} + tar@7.5.22: + resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==} engines: {node: '>=18'} tinybench@2.9.0: @@ -4050,8 +3707,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.62.0: - resolution: {integrity: sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q==} + typescript-eslint@8.68.0: + resolution: {integrity: sha512-MHy0Y0ynqeEbx/S45+i/bBssdy3X6KNBfmJAP35GrgtNxu2TQ5K5xsFDhAnmsq1jvpdoZOPG1LGtJo0HWqYCrQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -4067,11 +3724,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - typescript@7.0.2: - resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} - engines: {node: '>=16.20.0'} - hasBin: true - unconfig-core@7.5.0: resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} @@ -4121,13 +3773,13 @@ packages: resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} engines: {node: '>=18.12.0'} - vite@8.1.0: - resolution: {integrity: sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==} + vite@8.2.2: + resolution: {integrity: sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.3.0 + '@vitejs/devtools': ^0.4.0 || ^0.5.0 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -4242,8 +3894,8 @@ packages: bundledDependencies: - node-pre-gyp - ws@8.21.0: - resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + ws@8.21.3: + resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -4254,8 +3906,8 @@ packages: utf-8-validate: optional: true - wsl-utils@0.3.1: - resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} + wsl-utils@1.0.0: + resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==} engines: {node: '>=20'} y18n@5.0.8: @@ -4286,8 +3938,8 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yoctocolors@2.1.2: - resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + yoctocolors@2.2.0: + resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==} engines: {node: '>=18'} yuku-ast@0.8.7: @@ -4425,12 +4077,12 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commitlint/cli@21.2.2(@types/node@26.4.0)(conventional-commits-parser@7.1.2)(typescript@7.0.2)': + '@commitlint/cli@21.2.2(@types/node@26.4.0)(conventional-commits-parser@7.1.2)(typescript@6.0.3)': dependencies: '@commitlint/config-conventional': 21.2.2 '@commitlint/format': 21.2.2 '@commitlint/lint': 21.2.2 - '@commitlint/load': 21.2.2(@types/node@26.4.0)(typescript@7.0.2) + '@commitlint/load': 21.2.2(@types/node@26.4.0)(typescript@6.0.3) '@commitlint/read': 21.2.1(conventional-commits-parser@7.1.2) '@commitlint/types': 21.2.0 tinyexec: 1.3.0 @@ -4454,7 +4106,7 @@ snapshots: '@commitlint/ensure@21.2.0': dependencies: '@commitlint/types': 21.2.0 - es-toolkit: 1.51.0 + es-toolkit: 1.52.0 '@commitlint/execute-rule@21.0.1': {} @@ -4475,15 +4127,15 @@ snapshots: '@commitlint/rules': 21.2.2 '@commitlint/types': 21.2.0 - '@commitlint/load@21.2.2(@types/node@26.4.0)(typescript@7.0.2)': + '@commitlint/load@21.2.2(@types/node@26.4.0)(typescript@6.0.3)': dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/execute-rule': 21.0.1 '@commitlint/resolve-extends': 21.2.2 '@commitlint/types': 21.2.0 - cosmiconfig: 9.0.2(typescript@7.0.2) - cosmiconfig-typescript-loader: 6.3.0(@types/node@26.4.0)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2) - es-toolkit: 1.51.0 + cosmiconfig: 9.0.2(typescript@6.0.3) + cosmiconfig-typescript-loader: 6.3.0(@types/node@26.4.0)(cosmiconfig@9.0.2(typescript@6.0.3))(typescript@6.0.3) + es-toolkit: 1.52.0 is-plain-obj: 4.1.0 picocolors: 1.1.1 transitivePeerDependencies: @@ -4512,7 +4164,7 @@ snapshots: dependencies: '@commitlint/config-validator': 21.2.0 '@commitlint/types': 21.2.0 - es-toolkit: 1.51.0 + es-toolkit: 1.52.0 global-directory: 5.0.0 resolve-from: 5.0.0 @@ -4559,22 +4211,6 @@ snapshots: '@dprint/toml@0.7.0': {} - '@emnapi/core@1.11.1': - dependencies: - '@emnapi/wasi-threads': 1.2.2 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@1.11.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.2.2': - dependencies: - tslib: 2.8.1 - optional: true - '@eslint-community/eslint-utils@4.10.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))': dependencies: eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) @@ -4613,8 +4249,8 @@ snapshots: dependencies: '@favware/colorette-spinner': 1.0.1 '@octokit/auth-token': 6.0.0 - '@octokit/core': 7.0.6 - '@octokit/plugin-retry': 8.1.0(@octokit/core@7.0.6) + '@octokit/core': 7.0.7 + '@octokit/plugin-retry': 8.1.1(@octokit/core@7.0.7) '@sapphire/result': 2.8.0 '@sapphire/utilities': 3.18.2 colorette: 2.0.20 @@ -4622,9 +4258,9 @@ snapshots: conventional-recommended-bump: 11.2.0 execa: 9.6.1 git-cliff: 2.13.1 - js-yaml: 4.3.0 + js-yaml: 4.3.2 semver: 7.8.5 - smol-toml: 1.7.0 + smol-toml: 1.8.0 '@favware/colorette-spinner@1.0.1': dependencies: @@ -4655,27 +4291,27 @@ snapshots: '@inquirer/ansi@2.0.7': {} - '@inquirer/checkbox@5.2.1(@types/node@26.4.0)': + '@inquirer/checkbox@5.2.3(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/confirm@6.1.1(@types/node@26.4.0)': + '@inquirer/confirm@6.3.0(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/core@11.2.1(@types/node@26.4.0)': + '@inquirer/core@12.0.1(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@26.4.0) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 @@ -4683,92 +4319,107 @@ snapshots: optionalDependencies: '@types/node': 26.4.0 - '@inquirer/editor@5.2.2(@types/node@26.4.0)': + '@inquirer/editor@5.3.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/external-editor': 3.0.3(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/external-editor': 3.0.4(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/expand@5.1.1(@types/node@26.4.0)': + '@inquirer/expand@5.1.3(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/external-editor@3.0.3(@types/node@26.4.0)': + '@inquirer/external-editor@3.0.4(@types/node@26.4.0)': dependencies: chardet: 2.2.0 - iconv-lite: 0.7.2 + iconv-lite: 0.7.3 optionalDependencies: '@types/node': 26.4.0 - '@inquirer/figures@2.0.7': {} + '@inquirer/figures@2.0.8': {} - '@inquirer/input@5.1.2(@types/node@26.4.0)': + '@inquirer/input@5.1.4(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/number@4.1.1(@types/node@26.4.0)': + '@inquirer/number@4.2.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/password@5.1.1(@types/node@26.4.0)': + '@inquirer/password@5.2.0(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 '@inquirer/prompts@8.5.2(@types/node@26.4.0)': dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@26.4.0) - '@inquirer/confirm': 6.1.1(@types/node@26.4.0) - '@inquirer/editor': 5.2.2(@types/node@26.4.0) - '@inquirer/expand': 5.1.1(@types/node@26.4.0) - '@inquirer/input': 5.1.2(@types/node@26.4.0) - '@inquirer/number': 4.1.1(@types/node@26.4.0) - '@inquirer/password': 5.1.1(@types/node@26.4.0) - '@inquirer/rawlist': 5.3.1(@types/node@26.4.0) - '@inquirer/search': 4.2.1(@types/node@26.4.0) - '@inquirer/select': 5.2.1(@types/node@26.4.0) + '@inquirer/checkbox': 5.2.3(@types/node@26.4.0) + '@inquirer/confirm': 6.3.0(@types/node@26.4.0) + '@inquirer/editor': 5.3.1(@types/node@26.4.0) + '@inquirer/expand': 5.1.3(@types/node@26.4.0) + '@inquirer/input': 5.1.4(@types/node@26.4.0) + '@inquirer/number': 4.2.1(@types/node@26.4.0) + '@inquirer/password': 5.2.0(@types/node@26.4.0) + '@inquirer/rawlist': 5.3.3(@types/node@26.4.0) + '@inquirer/search': 4.3.1(@types/node@26.4.0) + '@inquirer/select': 5.2.3(@types/node@26.4.0) + optionalDependencies: + '@types/node': 26.4.0 + + '@inquirer/prompts@8.7.0(@types/node@26.4.0)': + dependencies: + '@inquirer/checkbox': 5.2.3(@types/node@26.4.0) + '@inquirer/confirm': 6.3.0(@types/node@26.4.0) + '@inquirer/editor': 5.3.1(@types/node@26.4.0) + '@inquirer/expand': 5.1.3(@types/node@26.4.0) + '@inquirer/input': 5.1.4(@types/node@26.4.0) + '@inquirer/number': 4.2.1(@types/node@26.4.0) + '@inquirer/password': 5.2.0(@types/node@26.4.0) + '@inquirer/rawlist': 5.3.3(@types/node@26.4.0) + '@inquirer/search': 4.3.1(@types/node@26.4.0) + '@inquirer/select': 5.2.3(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/rawlist@5.3.1(@types/node@26.4.0)': + '@inquirer/rawlist@5.3.3(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/search@4.2.1(@types/node@26.4.0)': + '@inquirer/search@4.3.1(@types/node@26.4.0)': dependencies: - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/select@5.2.1(@types/node@26.4.0)': + '@inquirer/select@5.2.3(@types/node@26.4.0)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@26.4.0) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@26.4.0) + '@inquirer/core': 12.0.1(@types/node@26.4.0) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@26.4.0) optionalDependencies: '@types/node': 26.4.0 - '@inquirer/type@4.0.7(@types/node@26.4.0)': + '@inquirer/type@4.1.0(@types/node@26.4.0)': optionalDependencies: '@types/node': 26.4.0 @@ -4778,17 +4429,17 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@mapbox/node-pre-gyp@2.0.3(supports-color@10.2.2)': dependencies: @@ -4798,7 +4449,7 @@ snapshots: node-fetch: 2.7.0 nopt: 8.1.0 semver: 7.8.5 - tar: 7.5.19 + tar: 7.5.22 transitivePeerDependencies: - encoding - supports-color @@ -4859,19 +4510,19 @@ snapshots: dependencies: '@angular-devkit/schematics': 22.1.6(chokidar@5.0.0) '@angular-devkit/schematics-cli': 22.1.6(@types/node@26.4.0)(chokidar@5.0.0) - '@inquirer/prompts': 8.5.2(@types/node@26.4.0) + '@inquirer/prompts': 8.7.0(@types/node@26.4.0) '@nanoforge-dev/loader-client': 1.4.0 '@nanoforge-dev/loader-server': 1.4.0 '@nanoforge-dev/schematics': 2.2.1(chokidar@5.0.0) ansis: 4.3.1 - bun: 1.3.14 + bun: 1.4.0 chokidar: 5.0.0 class-transformer: 0.5.1 class-validator: 0.15.1 commander: 15.0.0 dotenv: 17.4.2 node-emoji: 2.2.0 - open: 11.0.0 + open: 11.0.1 ora: 9.4.1 rc9: 3.0.1 reflect-metadata: 0.2.2 @@ -4882,19 +4533,19 @@ snapshots: '@nanoforge-dev/editor@0.1.4': dependencies: - bun: 1.3.14 + bun: 1.4.0 class-transformer: 0.5.1 class-validator: 0.15.1 dotenv: 17.4.2 micromatch: 4.0.8 - tar: 7.5.19 + tar: 7.5.22 typescript: 6.0.3 optional: true '@nanoforge-dev/loader-client@1.4.0': dependencies: '@nanoforge-dev/loader-website': 1.4.0 - bun: 1.3.14 + bun: 1.4.0 commander: 15.0.0 '@nanoforge-dev/loader-server@1.4.0': @@ -4911,25 +4562,8 @@ snapshots: transitivePeerDependencies: - chokidar - '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@tybys/wasm-util': 0.10.3 - optional: true - '@octokit/auth-token@6.0.0': {} - '@octokit/core@7.0.6': - dependencies: - '@octokit/auth-token': 6.0.0 - '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.10 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - before-after-hook: 4.0.0 - universal-user-agent: 7.0.3 - '@octokit/core@7.0.7': dependencies: '@octokit/auth-token': 6.0.0 @@ -4940,22 +4574,11 @@ snapshots: before-after-hook: 4.0.0 universal-user-agent: 7.0.3 - '@octokit/endpoint@11.0.3': - dependencies: - '@octokit/types': 16.0.0 - universal-user-agent: 7.0.3 - '@octokit/endpoint@11.0.4': dependencies: '@octokit/types': 17.0.0 universal-user-agent: 7.0.3 - '@octokit/graphql@9.0.3': - dependencies: - '@octokit/request': 10.0.10 - '@octokit/types': 16.0.0 - universal-user-agent: 7.0.3 - '@octokit/graphql@9.0.4': dependencies: '@octokit/request': 10.0.15 @@ -4976,30 +4599,17 @@ snapshots: '@octokit/core': 7.0.7 '@octokit/types': 16.0.0 - '@octokit/plugin-retry@8.1.0(@octokit/core@7.0.6)': + '@octokit/plugin-retry@8.1.1(@octokit/core@7.0.7)': dependencies: - '@octokit/core': 7.0.6 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/core': 7.0.7 + '@octokit/request-error': 7.1.1 + '@octokit/types': 17.0.0 bottleneck: 2.19.5 - '@octokit/request-error@7.1.0': - dependencies: - '@octokit/types': 16.0.0 - '@octokit/request-error@7.1.1': dependencies: '@octokit/types': 17.0.0 - '@octokit/request@10.0.10': - dependencies: - '@octokit/endpoint': 11.0.3 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - content-type: 2.0.0 - json-with-bigint: 3.5.8 - universal-user-agent: 7.0.3 - '@octokit/request@10.0.15': dependencies: '@octokit/endpoint': 11.0.4 @@ -5017,56 +4627,42 @@ snapshots: dependencies: '@octokit/openapi-types': 28.0.0 - '@oven/bun-darwin-aarch64@1.3.14': - optional: true - - '@oven/bun-darwin-x64-baseline@1.3.14': - optional: true - - '@oven/bun-darwin-x64@1.3.14': - optional: true - - '@oven/bun-freebsd-aarch64@1.3.14': - optional: true - - '@oven/bun-freebsd-x64@1.3.14': + '@oven/bun-darwin-aarch64@1.4.0': optional: true - '@oven/bun-linux-aarch64-android@1.3.14': + '@oven/bun-darwin-x64@1.4.0': optional: true - '@oven/bun-linux-aarch64-musl@1.3.14': + '@oven/bun-freebsd-aarch64@1.4.0': optional: true - '@oven/bun-linux-aarch64@1.3.14': + '@oven/bun-freebsd-x64@1.4.0': optional: true - '@oven/bun-linux-x64-android@1.3.14': + '@oven/bun-linux-aarch64-android@1.4.0': optional: true - '@oven/bun-linux-x64-baseline@1.3.14': + '@oven/bun-linux-aarch64-musl@1.4.0': optional: true - '@oven/bun-linux-x64-musl-baseline@1.3.14': + '@oven/bun-linux-aarch64@1.4.0': optional: true - '@oven/bun-linux-x64-musl@1.3.14': + '@oven/bun-linux-x64-android@1.4.0': optional: true - '@oven/bun-linux-x64@1.3.14': + '@oven/bun-linux-x64-musl@1.4.0': optional: true - '@oven/bun-windows-aarch64@1.3.14': + '@oven/bun-linux-x64@1.4.0': optional: true - '@oven/bun-windows-x64-baseline@1.3.14': + '@oven/bun-windows-aarch64@1.4.0': optional: true - '@oven/bun-windows-x64@1.3.14': + '@oven/bun-windows-x64@1.4.0': optional: true - '@oxc-project/types@0.139.0': {} - '@oxc-project/types@0.147.0': {} '@oxfmt/binding-android-arm-eabi@0.35.0': @@ -5135,94 +4731,45 @@ snapshots: '@rolldown/binding-android-arm-eabi@1.2.6': optional: true - '@rolldown/binding-android-arm64@1.1.5': - optional: true - '@rolldown/binding-android-arm64@1.2.6': optional: true - '@rolldown/binding-darwin-arm64@1.1.5': - optional: true - '@rolldown/binding-darwin-arm64@1.2.6': optional: true - '@rolldown/binding-darwin-x64@1.1.5': - optional: true - '@rolldown/binding-darwin-x64@1.2.6': optional: true - '@rolldown/binding-freebsd-x64@1.1.5': - optional: true - '@rolldown/binding-freebsd-x64@1.2.6': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': - optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.2.6': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.5': - optional: true - '@rolldown/binding-linux-arm64-gnu@1.2.6': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.5': - optional: true - '@rolldown/binding-linux-arm64-musl@1.2.6': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.5': - optional: true - '@rolldown/binding-linux-ppc64-gnu@1.2.6': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.5': - optional: true - '@rolldown/binding-linux-s390x-gnu@1.2.6': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.5': - optional: true - '@rolldown/binding-linux-x64-gnu@1.2.6': optional: true - '@rolldown/binding-linux-x64-musl@1.1.5': - optional: true - '@rolldown/binding-linux-x64-musl@1.2.6': optional: true - '@rolldown/binding-openharmony-arm64@1.1.5': - optional: true - '@rolldown/binding-openharmony-arm64@1.2.6': optional: true - '@rolldown/binding-wasm32-wasi@1.1.5': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - optional: true - - '@rolldown/binding-win32-arm64-msvc@1.1.5': - optional: true - '@rolldown/binding-win32-arm64-msvc@1.2.6': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.5': - optional: true - '@rolldown/binding-win32-x64-msvc@1.2.6': optional: true @@ -5356,11 +4903,6 @@ snapshots: '@turbo/windows-arm64@2.10.12': optional: true - '@tybys/wasm-util@0.10.3': - dependencies: - tslib: 2.8.1 - optional: true - '@types/argparse@1.0.38': {} '@types/chai@5.2.3': @@ -5391,157 +4933,97 @@ snapshots: dependencies: '@types/node': 26.4.0 - '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': + '@typescript-eslint/eslint-plugin@8.68.0(@typescript-eslint/parser@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/type-utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/visitor-keys': 8.62.0 + '@typescript-eslint/parser': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/type-utils': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.68.0 eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - ignore: 7.0.5 + ignore: 7.0.6 natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@7.0.2) - typescript: 7.0.2 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': + '@typescript-eslint/parser@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/visitor-keys': 8.62.0 + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.68.0 debug: 4.4.3(supports-color@10.2.2) eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - typescript: 7.0.2 + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.62.0(supports-color@10.2.2)(typescript@7.0.2)': + '@typescript-eslint/project-service@8.68.0(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@7.0.2) - '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/tsconfig-utils': 8.68.0(typescript@6.0.3) + '@typescript-eslint/types': 8.68.0 debug: 4.4.3(supports-color@10.2.2) - typescript: 7.0.2 + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.62.0': + '@typescript-eslint/scope-manager@8.68.0': dependencies: - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/visitor-keys': 8.62.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/visitor-keys': 8.68.0 - '@typescript-eslint/tsconfig-utils@8.62.0(typescript@7.0.2)': + '@typescript-eslint/tsconfig-utils@8.68.0(typescript@6.0.3)': dependencies: - typescript: 7.0.2 + typescript: 6.0.3 - '@typescript-eslint/type-utils@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': + '@typescript-eslint/type-utils@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) debug: 4.4.3(supports-color@10.2.2) eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - ts-api-utils: 2.5.0(typescript@7.0.2) - typescript: 7.0.2 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.62.0': {} + '@typescript-eslint/types@8.68.0': {} - '@typescript-eslint/typescript-estree@8.62.0(supports-color@10.2.2)(typescript@7.0.2)': + '@typescript-eslint/typescript-estree@8.68.0(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@7.0.2) - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/visitor-keys': 8.62.0 + '@typescript-eslint/project-service': 8.68.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.68.0(typescript@6.0.3) + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/visitor-keys': 8.68.0 debug: 4.4.3(supports-color@10.2.2) minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 - ts-api-utils: 2.5.0(typescript@7.0.2) - typescript: 7.0.2 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2)': + '@typescript-eslint/utils@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) - '@typescript-eslint/scope-manager': 8.62.0 - '@typescript-eslint/types': 8.62.0 - '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/scope-manager': 8.68.0 + '@typescript-eslint/types': 8.68.0 + '@typescript-eslint/typescript-estree': 8.68.0(supports-color@10.2.2)(typescript@6.0.3) eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - typescript: 7.0.2 + typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.62.0': + '@typescript-eslint/visitor-keys@8.68.0': dependencies: - '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/types': 8.68.0 eslint-visitor-keys: 5.0.1 - '@typescript/typescript-aix-ppc64@7.0.2': - optional: true - - '@typescript/typescript-darwin-arm64@7.0.2': - optional: true - - '@typescript/typescript-darwin-x64@7.0.2': - optional: true - - '@typescript/typescript-freebsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-freebsd-x64@7.0.2': - optional: true - - '@typescript/typescript-linux-arm64@7.0.2': - optional: true - - '@typescript/typescript-linux-arm@7.0.2': - optional: true - - '@typescript/typescript-linux-loong64@7.0.2': - optional: true - - '@typescript/typescript-linux-mips64el@7.0.2': - optional: true - - '@typescript/typescript-linux-ppc64@7.0.2': - optional: true - - '@typescript/typescript-linux-riscv64@7.0.2': - optional: true - - '@typescript/typescript-linux-s390x@7.0.2': - optional: true - - '@typescript/typescript-linux-x64@7.0.2': - optional: true - - '@typescript/typescript-netbsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-netbsd-x64@7.0.2': - optional: true - - '@typescript/typescript-openbsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-openbsd-x64@7.0.2': - optional: true - - '@typescript/typescript-sunos-x64@7.0.2': - optional: true - - '@typescript/typescript-win32-arm64@7.0.2': - optional: true - - '@typescript/typescript-win32-x64@7.0.2': - optional: true - '@vitest/coverage-v8@4.1.11(vitest@4.1.11)': dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -5554,7 +5036,7 @@ snapshots: obug: 2.1.4 std-env: 4.2.0 tinyrainbow: 3.1.1 - vitest: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + vitest: 4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) '@vitest/expect@4.1.11': dependencies: @@ -5565,13 +5047,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.11(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0))': + '@vitest/mocker@4.1.11(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.11 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0) + vite: 8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0) '@vitest/pretty-format@4.1.11': dependencies: @@ -5731,7 +5213,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} + ansi-regex@6.3.0: {} ansi-styles@6.2.3: {} @@ -5788,24 +5270,20 @@ snapshots: fill-range: 7.1.1 optional: true - bun@1.3.14: + bun@1.4.0: optionalDependencies: - '@oven/bun-darwin-aarch64': 1.3.14 - '@oven/bun-darwin-x64': 1.3.14 - '@oven/bun-darwin-x64-baseline': 1.3.14 - '@oven/bun-freebsd-aarch64': 1.3.14 - '@oven/bun-freebsd-x64': 1.3.14 - '@oven/bun-linux-aarch64': 1.3.14 - '@oven/bun-linux-aarch64-android': 1.3.14 - '@oven/bun-linux-aarch64-musl': 1.3.14 - '@oven/bun-linux-x64': 1.3.14 - '@oven/bun-linux-x64-android': 1.3.14 - '@oven/bun-linux-x64-baseline': 1.3.14 - '@oven/bun-linux-x64-musl': 1.3.14 - '@oven/bun-linux-x64-musl-baseline': 1.3.14 - '@oven/bun-windows-aarch64': 1.3.14 - '@oven/bun-windows-x64': 1.3.14 - '@oven/bun-windows-x64-baseline': 1.3.14 + '@oven/bun-darwin-aarch64': 1.4.0 + '@oven/bun-darwin-x64': 1.4.0 + '@oven/bun-freebsd-aarch64': 1.4.0 + '@oven/bun-freebsd-x64': 1.4.0 + '@oven/bun-linux-aarch64': 1.4.0 + '@oven/bun-linux-aarch64-android': 1.4.0 + '@oven/bun-linux-aarch64-musl': 1.4.0 + '@oven/bun-linux-x64': 1.4.0 + '@oven/bun-linux-x64-android': 1.4.0 + '@oven/bun-linux-x64-musl': 1.4.0 + '@oven/bun-windows-aarch64': 1.4.0 + '@oven/bun-windows-x64': 1.4.0 bundle-name@4.1.0: dependencies: @@ -5842,7 +5320,7 @@ snapshots: chokidar@5.0.0: dependencies: - readdirp: 5.0.0 + readdirp: 5.1.1 chownr@3.0.0: {} @@ -5851,13 +5329,13 @@ snapshots: class-validator@0.14.4: dependencies: '@types/validator': 13.15.10 - libphonenumber-js: 1.13.7 + libphonenumber-js: 1.13.12 validator: 13.15.35 class-validator@0.15.1: dependencies: '@types/validator': 13.15.10 - libphonenumber-js: 1.13.7 + libphonenumber-js: 1.13.12 validator: 13.15.35 cli-cursor@5.0.0: @@ -5896,8 +5374,6 @@ snapshots: consola@3.4.2: {} - content-type@2.0.0: {} - content-type@3.0.0: {} conventional-changelog-angular@9.4.0: @@ -5932,21 +5408,21 @@ snapshots: convert-source-map@2.0.0: {} - cosmiconfig-typescript-loader@6.3.0(@types/node@26.4.0)(cosmiconfig@9.0.2(typescript@7.0.2))(typescript@7.0.2): + cosmiconfig-typescript-loader@6.3.0(@types/node@26.4.0)(cosmiconfig@9.0.2(typescript@6.0.3))(typescript@6.0.3): dependencies: '@types/node': 26.4.0 - cosmiconfig: 9.0.2(typescript@7.0.2) + cosmiconfig: 9.0.2(typescript@6.0.3) jiti: 2.6.1 - typescript: 7.0.2 + typescript: 6.0.3 - cosmiconfig@9.0.2(typescript@7.0.2): + cosmiconfig@9.0.2(typescript@6.0.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 js-yaml: 4.3.2 parse-json: 5.2.0 optionalDependencies: - typescript: 7.0.2 + typescript: 6.0.3 cross-spawn@7.0.6: dependencies: @@ -5964,7 +5440,7 @@ snapshots: default-browser-id@5.0.1: {} - default-browser@5.5.0: + default-browser@5.5.1: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.1 @@ -6036,7 +5512,7 @@ snapshots: dependencies: es-errors: 1.3.0 - es-toolkit@1.51.0: {} + es-toolkit@1.52.0: {} escalade@3.2.0: {} @@ -6054,7 +5530,7 @@ snapshots: eslint-rule-docs: 1.1.235 log-symbols: 7.0.1 plur: 5.1.0 - string-width: 8.2.1 + string-width: 8.2.2 supports-hyperlinks: 4.5.0 eslint-formatting-reporter@0.0.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)): @@ -6072,7 +5548,7 @@ snapshots: eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) eslint-formatting-reporter: 0.0.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2)) eslint-parser-plain: 0.1.1 - ohash: 2.0.11 + ohash: 2.0.12 oxfmt: 0.35.0 prettier: 3.9.6 synckit: 0.11.13 @@ -6169,10 +5645,10 @@ snapshots: is-plain-obj: 4.1.0 is-stream: 4.0.1 npm-run-path: 6.0.0 - pretty-ms: 9.3.0 + pretty-ms: 9.3.1 signal-exit: 4.1.0 strip-final-newline: 4.0.0 - yoctocolors: 2.1.2 + yoctocolors: 2.2.0 expect-type@1.4.0: {} @@ -6314,7 +5790,7 @@ snapshots: dependencies: ini: 6.0.0 - globals@17.7.0: {} + globals@17.11.0: {} gopd@1.2.0: {} @@ -6353,13 +5829,13 @@ snapshots: husky@9.1.7: {} - iconv-lite@0.7.2: + iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 ignore@5.3.2: {} - ignore@7.0.5: {} + ignore@7.0.6: {} import-fresh@3.3.1: dependencies: @@ -6479,10 +5955,6 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@4.3.0: - dependencies: - argparse: 2.0.1 - js-yaml@4.3.2: dependencies: argparse: 2.0.1 @@ -6501,8 +5973,6 @@ snapshots: json-with-bigint@3.5.12: {} - json-with-bigint@3.5.8: {} - jsonc-parser@3.3.1: {} jsonfile@6.2.1: @@ -6515,14 +5985,14 @@ snapshots: dependencies: json-buffer: 3.0.1 - konva@10.3.0: {} + konva@10.3.2: {} levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - libphonenumber-js@1.13.7: {} + libphonenumber-js@1.13.12: {} lightningcss-android-arm64@1.33.0: optional: true @@ -6575,7 +6045,7 @@ snapshots: lines-and-columns@1.2.4: {} - lint-staged@17.3.0: + lint-staged@17.4.1: dependencies: picomatch: 4.0.7 string-argv: 0.3.2 @@ -6598,7 +6068,7 @@ snapshots: log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 - yoctocolors: 2.1.2 + yoctocolors: 2.2.0 loose-envify@1.4.0: dependencies: @@ -6610,11 +6080,11 @@ snapshots: magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 magic-string@1.0.0: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 magicast@0.5.4: dependencies: @@ -6660,7 +6130,7 @@ snapshots: dependencies: minipass: 7.1.3 - mint-tsdocs@0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.4.0)(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(react-dom@18.3.1(react@18.3.1))(supports-color@10.2.2)(typescript@7.0.2): + mint-tsdocs@0.0.8(@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/node@26.4.0)(@typescript-eslint/parser@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(react-dom@18.3.1(react@18.3.1))(supports-color@10.2.2)(typescript@6.0.3): dependencies: '@clack/prompts': 0.11.0 '@microsoft/api-extractor': 7.59.0(@types/node@26.4.0) @@ -6673,7 +6143,7 @@ snapshots: chalk: 5.6.2 cli-table3: 0.6.5 clsx: 2.1.1 - cosmiconfig: 9.0.2(typescript@7.0.2) + cosmiconfig: 9.0.2(typescript@6.0.3) debug: 4.4.3(supports-color@10.2.2) ejs: 3.1.10 is-unicode-supported: 2.1.0 @@ -6682,7 +6152,7 @@ snapshots: react: 18.3.1 resolve: 1.22.12 optionalDependencies: - '@typescript-eslint/parser': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/parser': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) transitivePeerDependencies: - '@headlessui/react' @@ -6737,20 +6207,20 @@ snapshots: obug@2.1.4: {} - ohash@2.0.11: {} + ohash@2.0.12: {} onetime@7.0.0: dependencies: mimic-function: 5.0.1 - open@11.0.0: + open@11.0.1: dependencies: - default-browser: 5.5.0 + default-browser: 5.5.1 define-lazy-prop: 3.0.0 is-in-ssh: 1.0.0 is-inside-container: 1.0.0 - powershell-utils: 0.1.0 - wsl-utils: 0.3.1 + powershell-utils: 0.2.0 + wsl-utils: 1.0.0 optionator@0.9.4: dependencies: @@ -6770,7 +6240,7 @@ snapshots: is-unicode-supported: 2.1.0 log-symbols: 7.0.1 stdin-discarder: 0.3.2 - string-width: 8.2.1 + string-width: 8.2.2 oxfmt@0.35.0: dependencies: @@ -6856,6 +6326,8 @@ snapshots: powershell-utils@0.1.0: {} + powershell-utils@0.2.0: {} + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.1: @@ -6864,7 +6336,7 @@ snapshots: prettier@3.9.6: {} - pretty-ms@9.3.0: + pretty-ms@9.3.1: dependencies: parse-ms: 4.0.0 @@ -6887,7 +6359,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - readdirp@5.0.0: {} + readdirp@5.1.1: {} reflect-metadata@0.2.2: {} @@ -6911,7 +6383,7 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 - rolldown-plugin-dts@0.27.14(rolldown@1.2.6)(typescript@7.0.2): + rolldown-plugin-dts@0.27.14(rolldown@1.2.6)(typescript@6.0.3): dependencies: dts-resolver: 3.0.0 get-tsconfig: 5.0.0-beta.5 @@ -6921,31 +6393,10 @@ snapshots: yuku-codegen: 0.8.7 yuku-parser: 0.8.7 optionalDependencies: - typescript: 7.0.2 + typescript: 6.0.3 transitivePeerDependencies: - oxc-resolver - rolldown@1.1.5: - dependencies: - '@oxc-project/types': 0.139.0 - '@rolldown/pluginutils': 1.0.1 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.5 - '@rolldown/binding-darwin-arm64': 1.1.5 - '@rolldown/binding-darwin-x64': 1.1.5 - '@rolldown/binding-freebsd-x64': 1.1.5 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 - '@rolldown/binding-linux-arm64-gnu': 1.1.5 - '@rolldown/binding-linux-arm64-musl': 1.1.5 - '@rolldown/binding-linux-ppc64-gnu': 1.1.5 - '@rolldown/binding-linux-s390x-gnu': 1.1.5 - '@rolldown/binding-linux-x64-gnu': 1.1.5 - '@rolldown/binding-linux-x64-musl': 1.1.5 - '@rolldown/binding-openharmony-arm64': 1.1.5 - '@rolldown/binding-wasm32-wasi': 1.1.5 - '@rolldown/binding-win32-arm64-msvc': 1.1.5 - '@rolldown/binding-win32-x64-msvc': 1.1.5 - rolldown@1.2.6: dependencies: '@oxc-project/types': 0.147.0 @@ -7018,7 +6469,7 @@ snapshots: dependencies: unicode-emoji-modifier-base: 1.0.0 - smol-toml@1.7.0: {} + smol-toml@1.8.0: {} source-map-js@1.2.1: {} @@ -7048,11 +6499,6 @@ snapshots: get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 - string-width@8.2.1: - dependencies: - get-east-asian-width: 1.6.0 - strip-ansi: 7.2.0 - string-width@8.2.2: dependencies: get-east-asian-width: 1.6.0 @@ -7064,7 +6510,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 strip-final-newline@4.0.0: {} @@ -7089,7 +6535,7 @@ snapshots: dependencies: '@pkgr/core': 0.3.6 - tar@7.5.19: + tar@7.5.22: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 @@ -7119,11 +6565,11 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@2.5.0(typescript@7.0.2): + ts-api-utils@2.5.0(typescript@6.0.3): dependencies: - typescript: 7.0.2 + typescript: 6.0.3 - tsdown@0.22.14(typescript@7.0.2)(unrun@0.3.1(synckit@0.11.13)): + tsdown@0.22.14(typescript@6.0.3)(unrun@0.3.1(synckit@0.11.13)): dependencies: ansis: 4.3.1 cac: 7.0.0 @@ -7134,14 +6580,14 @@ snapshots: obug: 2.1.4 picomatch: 4.0.7 rolldown: 1.2.6 - rolldown-plugin-dts: 0.27.14(rolldown@1.2.6)(typescript@7.0.2) + rolldown-plugin-dts: 0.27.14(rolldown@1.2.6)(typescript@6.0.3) tinyexec: 1.3.0 tinyglobby: 0.2.17 tree-kill: 1.2.2 unconfig-core: 7.5.0 verkit: 0.3.2 optionalDependencies: - typescript: 7.0.2 + typescript: 6.0.3 unrun: 0.3.1(synckit@0.11.13) transitivePeerDependencies: - '@typescript/native-preview' @@ -7166,44 +6612,20 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2): + typescript-eslint@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/parser': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/typescript-estree': 8.62.0(supports-color@10.2.2)(typescript@7.0.2) - '@typescript-eslint/utils': 8.62.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@7.0.2) + '@typescript-eslint/eslint-plugin': 8.68.0(@typescript-eslint/parser@8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/parser': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.68.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.68.0(eslint@10.9.1(jiti@2.6.1)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) eslint: 10.9.1(jiti@2.6.1)(supports-color@10.2.2) - typescript: 7.0.2 + typescript: 6.0.3 transitivePeerDependencies: - supports-color typescript@5.9.3: {} - typescript@6.0.3: - optional: true - - typescript@7.0.2: - optionalDependencies: - '@typescript/typescript-aix-ppc64': 7.0.2 - '@typescript/typescript-darwin-arm64': 7.0.2 - '@typescript/typescript-darwin-x64': 7.0.2 - '@typescript/typescript-freebsd-arm64': 7.0.2 - '@typescript/typescript-freebsd-x64': 7.0.2 - '@typescript/typescript-linux-arm': 7.0.2 - '@typescript/typescript-linux-arm64': 7.0.2 - '@typescript/typescript-linux-loong64': 7.0.2 - '@typescript/typescript-linux-mips64el': 7.0.2 - '@typescript/typescript-linux-ppc64': 7.0.2 - '@typescript/typescript-linux-riscv64': 7.0.2 - '@typescript/typescript-linux-s390x': 7.0.2 - '@typescript/typescript-linux-x64': 7.0.2 - '@typescript/typescript-netbsd-arm64': 7.0.2 - '@typescript/typescript-netbsd-x64': 7.0.2 - '@typescript/typescript-openbsd-arm64': 7.0.2 - '@typescript/typescript-openbsd-x64': 7.0.2 - '@typescript/typescript-sunos-x64': 7.0.2 - '@typescript/typescript-win32-arm64': 7.0.2 - '@typescript/typescript-win32-x64': 7.0.2 + typescript@6.0.3: {} unconfig-core@7.5.0: dependencies: @@ -7244,12 +6666,12 @@ snapshots: verkit@0.3.2: {} - vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0): + vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.7 postcss: 8.5.26 - rolldown: 1.1.5 + rolldown: 1.2.6 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 26.4.0 @@ -7257,10 +6679,10 @@ snapshots: jiti: 2.6.1 yaml: 2.9.0 - vitest@4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)): + vitest@4.1.11(@types/node@26.4.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(vite@8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -7277,7 +6699,7 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 8.1.0(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0) + vite: 8.2.2(@types/node@26.4.0)(jiti@2.6.1)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 26.4.0 @@ -7326,9 +6748,9 @@ snapshots: optionalDependencies: domexception: 1.0.1 - ws@8.21.0: {} + ws@8.21.3: {} - wsl-utils@0.3.1: + wsl-utils@1.0.0: dependencies: is-wsl: 3.1.1 powershell-utils: 0.1.0 @@ -7355,7 +6777,7 @@ snapshots: yocto-queue@0.1.0: {} - yoctocolors@2.1.2: {} + yoctocolors@2.2.0: {} yuku-ast@0.8.7: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 3b19f0e6..1b51d742 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - packages/* + - modules/* - utils/* - e2e/game/** - example/** @@ -18,14 +19,14 @@ catalogs: '@favware/cliff-jumper': ^6.0.0 '@nanoforge-dev/actions': ^2.1.5 husky: ^9.1.7 - lint-staged: ^17.3.0 + lint-staged: ^17.4.1 config: class-transformer: ^0.5.1 class-validator: ^0.14.3 core: '@types/node': ^26.4.0 turbo: ^2.10.12 - typescript: ^7.0.2 + typescript: ^6.0.3 docs: '@microsoft/api-extractor': ^7.59.0 mint-tsdocs: ^0.0.8 diff --git a/tsdown.config.ts b/tsdown.config.ts index c73e0817..9b12b879 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -1,9 +1,14 @@ import { defineConfig } from "tsdown"; -export function createTsdownConfig() { +export function createTsdownConfig(options?: { + entry?: string | string[]; + outDir?: string; + tsconfig?: string; +}) { return defineConfig({ - entry: ["src/index.ts"], - outDir: "dist", + entry: options?.entry ?? ["src/index.ts"], + outDir: options?.outDir ?? "dist", + tsconfig: options?.tsconfig ?? "tsconfig.json", format: ["esm", "cjs"], shims: true, dts: true, diff --git a/packages/input/.gitignore b/utils/eslint-config/.gitignore similarity index 91% rename from packages/input/.gitignore rename to utils/eslint-config/.gitignore index e2764b6d..88ef62e8 100644 --- a/packages/input/.gitignore +++ b/utils/eslint-config/.gitignore @@ -12,40 +12,6 @@ # 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 @@ -257,8 +223,6 @@ dist .yarn/install-state.gz .pnp.* -### Private - # Turbo .turbo/ @@ -266,10 +230,5 @@ dist src/**/*.js src/**/*.d.ts -# pubilc directory -public/ -compile_commands.json -emsdk/ - # mint-tsdocs cache docs/.tsdocs/ diff --git a/utils/eslint-config/LICENSE b/utils/eslint-config/LICENSE index 62c6400b..46724861 100644 --- a/utils/eslint-config/LICENSE +++ b/utils/eslint-config/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/utils/eslint-config/README.md b/utils/eslint-config/README.md index 107d53c5..19743e86 100644 --- a/utils/eslint-config/README.md +++ b/utils/eslint-config/README.md @@ -19,7 +19,7 @@ ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install --save-dev @nanoforge-dev/utils-eslint-config diff --git a/utils/eslint-config/package.json b/utils/eslint-config/package.json index e9e050ce..56db0e85 100644 --- a/utils/eslint-config/package.json +++ b/utils/eslint-config/package.json @@ -8,8 +8,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -58,7 +59,7 @@ "eslint": "catalog:lint", "prettier": "catalog:lint" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" }, diff --git a/packages/sound/.gitignore b/utils/prettier-config/.gitignore similarity index 91% rename from packages/sound/.gitignore rename to utils/prettier-config/.gitignore index e2764b6d..88ef62e8 100644 --- a/packages/sound/.gitignore +++ b/utils/prettier-config/.gitignore @@ -12,40 +12,6 @@ # 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 @@ -257,8 +223,6 @@ dist .yarn/install-state.gz .pnp.* -### Private - # Turbo .turbo/ @@ -266,10 +230,5 @@ dist src/**/*.js src/**/*.d.ts -# pubilc directory -public/ -compile_commands.json -emsdk/ - # mint-tsdocs cache docs/.tsdocs/ diff --git a/utils/prettier-config/LICENSE b/utils/prettier-config/LICENSE index 62c6400b..46724861 100644 --- a/utils/prettier-config/LICENSE +++ b/utils/prettier-config/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright © 2025 NanoForge +Copyright © 2026 NanoForge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/utils/prettier-config/README.md b/utils/prettier-config/README.md index b381f4f6..a27ee5ce 100644 --- a/utils/prettier-config/README.md +++ b/utils/prettier-config/README.md @@ -19,7 +19,7 @@ ## Installation -**Node.js 25 or newer is required.** +**Node.js 26 or newer is required.** ```sh npm install --save-dev @nanoforge-dev/utils-prettier-config diff --git a/utils/prettier-config/package.json b/utils/prettier-config/package.json index dd835c29..9416f4a3 100644 --- a/utils/prettier-config/package.json +++ b/utils/prettier-config/package.json @@ -8,8 +8,9 @@ "license": "MIT", "contributors": [ "Bill ", - "Exelo ", + "Exelo ", "Fexkoser ", + "Josephine ", "Tchips " ], "files": [ @@ -47,7 +48,7 @@ "@trivago/prettier-plugin-sort-imports": "catalog:lint", "prettier": "catalog:lint" }, - "packageManager": "pnpm@11.24.0", + "packageManager": "pnpm@12.0.0", "engines": { "node": "26" },