diff --git a/e2e/cli-help.test.ts b/e2e/cli-help.test.ts index 96d045f..668bab7 100644 --- a/e2e/cli-help.test.ts +++ b/e2e/cli-help.test.ts @@ -93,9 +93,7 @@ describe("nf start --help", () => { expect(stdout).toContain("start your game"); expect(stdout).toContain("--directory"); expect(stdout).toContain("--config"); - expect(stdout).toContain("--client-port"); - expect(stdout).toContain("--game-exposure-port"); - expect(stdout).toContain("--server-port"); + expect(stdout).toContain("--port"); expect(stdout).toContain("--watch"); }); }); diff --git a/package.json b/package.json index 86b0220..6aa37b8 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "class-transformer": "catalog:libs", "class-validator": "catalog:libs", "commander": "catalog:cli", + "dotenv": "catalog:libs", "node-emoji": "catalog:cli", "ora": "catalog:cli", "rc9": "catalog:libs", @@ -78,7 +79,6 @@ "@types/inquirer": "catalog:cli", "@types/node": "catalog:core", "@vitest/coverage-v8": "catalog:tests", - "dotenv": "catalog:build", "eslint": "catalog:lint", "husky": "catalog:ci", "lint-staged": "catalog:ci", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c7a6c99..fd4e26a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,9 +6,6 @@ settings: catalogs: build: - dotenv: - specifier: ^17.3.1 - version: 17.3.1 tsup: specifier: ^8.5.1 version: 8.5.1 @@ -55,8 +52,8 @@ catalogs: version: 9.3.0 core: '@types/node': - specifier: ^25.3.3 - version: 25.3.3 + specifier: ^25.3.5 + version: 25.3.5 bun: specifier: ^1.3.10 version: 1.3.10 @@ -70,6 +67,9 @@ catalogs: class-validator: specifier: ^0.15.1 version: 0.15.1 + dotenv: + specifier: ^17.3.1 + version: 17.3.1 rc9: specifier: ^3.0.0 version: 3.0.0 @@ -87,18 +87,18 @@ catalogs: specifier: ^6.0.2 version: 6.0.2 eslint: - specifier: ^10.0.2 - version: 10.0.2 + specifier: ^10.0.3 + version: 10.0.3 prettier: specifier: ^3.8.1 version: 3.8.1 loader: '@nanoforge-dev/loader-client': + specifier: ^1.3.0 + version: 1.3.0 + '@nanoforge-dev/loader-server': specifier: ^1.2.0 version: 1.2.0 - '@nanoforge-dev/loader-server': - specifier: ^1.1.0 - version: 1.1.0 schematics: '@angular-devkit/schematics': specifier: ^21.2.1 @@ -126,16 +126,16 @@ importers: version: 21.2.1(chokidar@5.0.0) '@angular-devkit/schematics-cli': specifier: catalog:schematics - version: 21.2.1(@types/node@25.3.3)(chokidar@5.0.0) + version: 21.2.1(@types/node@25.3.5)(chokidar@5.0.0) '@inquirer/prompts': specifier: catalog:cli - version: 8.3.0(@types/node@25.3.3) + version: 8.3.0(@types/node@25.3.5) '@nanoforge-dev/loader-client': specifier: catalog:loader - version: 1.2.0 + version: 1.3.0 '@nanoforge-dev/loader-server': specifier: catalog:loader - version: 1.1.0 + version: 1.2.0 '@nanoforge-dev/schematics': specifier: catalog:schematics version: 1.2.0(chokidar@5.0.0) @@ -157,6 +157,9 @@ importers: commander: specifier: catalog:cli version: 14.0.3 + dotenv: + specifier: catalog:libs + version: 17.3.1 node-emoji: specifier: catalog:cli version: 2.2.0 @@ -172,7 +175,7 @@ importers: devDependencies: '@commitlint/cli': specifier: catalog:ci - version: 20.4.3(@types/node@25.3.3)(typescript@5.9.3) + version: 20.4.3(@types/node@25.3.5)(typescript@5.9.3) '@commitlint/config-conventional': specifier: catalog:ci version: 20.4.3 @@ -184,7 +187,7 @@ importers: version: 1.1.0 '@nanoforge-dev/utils-eslint-config': specifier: catalog:lint - version: 1.0.2(@types/eslint@9.6.1)(eslint@10.0.2(jiti@2.6.1))(prettier@3.8.1)(typescript@5.9.3) + version: 1.0.2(@types/eslint@9.6.1)(eslint@10.0.3(jiti@2.6.1))(prettier@3.8.1)(typescript@5.9.3) '@nanoforge-dev/utils-prettier-config': specifier: catalog:lint version: 1.0.2 @@ -196,16 +199,13 @@ importers: version: 9.0.9 '@types/node': specifier: catalog:core - version: 25.3.3 + version: 25.3.5 '@vitest/coverage-v8': specifier: catalog:tests - version: 4.0.18(vitest@4.0.18(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2)) - dotenv: - specifier: catalog:build - version: 17.3.1 + version: 4.0.18(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2)) eslint: specifier: catalog:lint - version: 10.0.2(jiti@2.6.1) + version: 10.0.3(jiti@2.6.1) husky: specifier: catalog:ci version: 9.1.7 @@ -223,7 +223,7 @@ importers: version: 5.9.3 vitest: specifier: catalog:tests - version: 4.0.18(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2) + version: 4.0.18(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2) packages: @@ -557,28 +557,28 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.23.2': - resolution: {integrity: sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==} + '@eslint/config-array@0.23.3': + resolution: {integrity: sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.5.2': - resolution: {integrity: sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==} + '@eslint/config-helpers@0.5.3': + resolution: {integrity: sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/core@1.1.0': - resolution: {integrity: sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==} + '@eslint/core@1.1.1': + resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/js@9.39.3': - resolution: {integrity: sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==} + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@3.0.2': - resolution: {integrity: sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==} + '@eslint/object-schema@3.0.3': + resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.6.0': - resolution: {integrity: sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==} + '@eslint/plugin-kit@0.6.1': + resolution: {integrity: sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@fastify/busboy@2.1.1': @@ -895,17 +895,17 @@ packages: resolution: {integrity: sha512-BTZyJ69Ax5nvMYqFRzj4WGvFTUW4W9JSDSaln4DwJmDtS3davkwphuXS85WEghQ1lpbp+gHuOUXu6Xj56gwW2w==} engines: {node: '25'} - '@nanoforge-dev/loader-client@1.2.0': - resolution: {integrity: sha512-iEzxcqfDpKJ2Y02sGTNcMsGqB7tXjLAYx2lW+mME0VD5uJT45Pt89mE9biYqBlFHSBNr5UdG+DmyiNFiZEXQcw==} + '@nanoforge-dev/loader-client@1.3.0': + resolution: {integrity: sha512-qD3mJ/IOo7Nq3ru4q4yxW0DRIIk2uS/+rwYO9GWJcUVodlJumbSmVrTAoZnnI6lKki2MsKp9RtJJwPB2vNlOXQ==} engines: {node: '25'} - '@nanoforge-dev/loader-server@1.1.0': - resolution: {integrity: sha512-U+AOZIzzCb3VPPkGR3OpUpAm97xEyndDXLHH/XA+XZMlPHx6h3n8hA7sJnN4szPqx5CQR8ssgnpwdgnI6lwNWQ==} - engines: {node: 24.11.0} + '@nanoforge-dev/loader-server@1.2.0': + resolution: {integrity: sha512-Fc209YxN2E5uU1P33u+Tr0GM0AoRG27Y7dDxXbTn285nzC2ePP4gVHdws+wE11CY54TnisWhjCislq5EIFxNgQ==} + engines: {node: '25'} - '@nanoforge-dev/loader-website@1.1.0': - resolution: {integrity: sha512-6taExH65vAfUpIVrWSzPzLsGkdXcdREjOjvgY4vOwXet3JXRtA6+yHjqp2kVg9Yrp+OA3iUPNXOsLRXOrfNVJw==} - engines: {node: 24.11.0} + '@nanoforge-dev/loader-website@1.2.0': + resolution: {integrity: sha512-gKFEQFt1+RIQyRzpVyjuaXib4nBLa4g3LNfy9TEMPlXe21IZy346L3RO5PmlVslPAYJuy5chUXfBE+BmE9BedA==} + engines: {node: '25'} '@nanoforge-dev/schematics@1.2.0': resolution: {integrity: sha512-ObxdyAi8D0Waj3gfuyzGuwEv7M9DTsYe81kv+2rduR6go/Wxbbt3FWykEZ7pWxXX9VgxmMxlptYRMrNEk7bLaA==} @@ -1372,8 +1372,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.3.3': - resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==} + '@types/node@25.3.5': + resolution: {integrity: sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==} '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} @@ -1829,8 +1829,8 @@ packages: eslint-rule-docs@1.1.235: resolution: {integrity: sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==} - eslint-scope@9.1.1: - resolution: {integrity: sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==} + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} eslint-visitor-keys@3.4.3: @@ -1841,8 +1841,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.0.2: - resolution: {integrity: sha512-uYixubwmqJZH+KLVYIVKY1JQt7tysXhtj21WSvjcSmU5SVNzMus1bgLe+pAt816yQ8opKfheVVoPLqvVMGejYw==} + eslint@10.0.3: + resolution: {integrity: sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1851,8 +1851,8 @@ packages: jiti: optional: true - espree@11.1.1: - resolution: {integrity: sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==} + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} esquery@1.7.0: @@ -2888,11 +2888,11 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/schematics-cli@21.2.1(@types/node@25.3.3)(chokidar@5.0.0)': + '@angular-devkit/schematics-cli@21.2.1(@types/node@25.3.5)(chokidar@5.0.0)': dependencies: '@angular-devkit/core': 21.2.1(chokidar@5.0.0) '@angular-devkit/schematics': 21.2.1(chokidar@5.0.0) - '@inquirer/prompts': 7.10.1(@types/node@25.3.3) + '@inquirer/prompts': 7.10.1(@types/node@25.3.5) transitivePeerDependencies: - '@types/node' - chokidar @@ -2956,11 +2956,11 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@commitlint/cli@20.4.3(@types/node@25.3.3)(typescript@5.9.3)': + '@commitlint/cli@20.4.3(@types/node@25.3.5)(typescript@5.9.3)': dependencies: '@commitlint/format': 20.4.3 '@commitlint/lint': 20.4.3 - '@commitlint/load': 20.4.3(@types/node@25.3.3)(typescript@5.9.3) + '@commitlint/load': 20.4.3(@types/node@25.3.5)(typescript@5.9.3) '@commitlint/read': 20.4.3 '@commitlint/types': 20.4.3 tinyexec: 1.0.2 @@ -3007,14 +3007,14 @@ snapshots: '@commitlint/rules': 20.4.3 '@commitlint/types': 20.4.3 - '@commitlint/load@20.4.3(@types/node@25.3.3)(typescript@5.9.3)': + '@commitlint/load@20.4.3(@types/node@25.3.5)(typescript@5.9.3)': dependencies: '@commitlint/config-validator': 20.4.3 '@commitlint/execute-rule': 20.0.0 '@commitlint/resolve-extends': 20.4.3 '@commitlint/types': 20.4.3 cosmiconfig: 9.0.1(typescript@5.9.3) - cosmiconfig-typescript-loader: 6.2.0(@types/node@25.3.3)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.2.0(@types/node@25.3.5)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3) is-plain-obj: 4.1.0 lodash.mergewith: 4.6.2 picocolors: 1.1.1 @@ -3157,36 +3157,36 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@10.0.2(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.0.3(jiti@2.6.1))': dependencies: - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.23.2': + '@eslint/config-array@0.23.3': dependencies: - '@eslint/object-schema': 3.0.2 + '@eslint/object-schema': 3.0.3 debug: 4.4.3 minimatch: 10.2.4 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.5.2': + '@eslint/config-helpers@0.5.3': dependencies: - '@eslint/core': 1.1.0 + '@eslint/core': 1.1.1 - '@eslint/core@1.1.0': + '@eslint/core@1.1.1': dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@9.39.3': {} + '@eslint/js@9.39.4': {} - '@eslint/object-schema@3.0.2': {} + '@eslint/object-schema@3.0.3': {} - '@eslint/plugin-kit@0.6.0': + '@eslint/plugin-kit@0.6.1': dependencies: - '@eslint/core': 1.1.0 + '@eslint/core': 1.1.1 levn: 0.4.1 '@fastify/busboy@2.1.1': {} @@ -3227,245 +3227,245 @@ snapshots: '@inquirer/ansi@2.0.3': {} - '@inquirer/checkbox@4.3.2(@types/node@25.3.3)': + '@inquirer/checkbox@4.3.2(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/type': 3.0.10(@types/node@25.3.5) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/checkbox@5.1.0(@types/node@25.3.3)': + '@inquirer/checkbox@5.1.0(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/confirm@5.1.21(@types/node@25.3.3)': + '@inquirer/confirm@5.1.21(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/confirm@6.0.8(@types/node@25.3.3)': + '@inquirer/confirm@6.0.8(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/core@10.3.2(@types/node@25.3.3)': + '@inquirer/core@10.3.2(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/type': 3.0.10(@types/node@25.3.5) 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': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/core@11.1.5(@types/node@25.3.3)': + '@inquirer/core@11.1.5(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 2.0.3 '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/type': 4.0.3(@types/node@25.3.5) cli-width: 4.1.0 fast-wrap-ansi: 0.2.0 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/editor@4.2.23(@types/node@25.3.3)': + '@inquirer/editor@4.2.23(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/external-editor': 1.0.3(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/external-editor': 1.0.3(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/editor@5.0.8(@types/node@25.3.3)': + '@inquirer/editor@5.0.8(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/external-editor': 2.0.3(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/external-editor': 2.0.3(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/expand@4.0.23(@types/node@25.3.3)': + '@inquirer/expand@4.0.23(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/expand@5.0.8(@types/node@25.3.3)': + '@inquirer/expand@5.0.8(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/external-editor@1.0.3(@types/node@25.3.3)': + '@inquirer/external-editor@1.0.3(@types/node@25.3.5)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/external-editor@2.0.3(@types/node@25.3.3)': + '@inquirer/external-editor@2.0.3(@types/node@25.3.5)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 '@inquirer/figures@1.0.15': {} '@inquirer/figures@2.0.3': {} - '@inquirer/input@4.3.1(@types/node@25.3.3)': + '@inquirer/input@4.3.1(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/input@5.0.8(@types/node@25.3.3)': + '@inquirer/input@5.0.8(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/number@3.0.23(@types/node@25.3.3)': + '@inquirer/number@3.0.23(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/number@4.0.8(@types/node@25.3.3)': + '@inquirer/number@4.0.8(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/password@4.0.23(@types/node@25.3.3)': + '@inquirer/password@4.0.23(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/password@5.0.8(@types/node@25.3.3)': + '@inquirer/password@5.0.8(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 - - '@inquirer/prompts@7.10.1(@types/node@25.3.3)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@25.3.3) - '@inquirer/confirm': 5.1.21(@types/node@25.3.3) - '@inquirer/editor': 4.2.23(@types/node@25.3.3) - '@inquirer/expand': 4.0.23(@types/node@25.3.3) - '@inquirer/input': 4.3.1(@types/node@25.3.3) - '@inquirer/number': 3.0.23(@types/node@25.3.3) - '@inquirer/password': 4.0.23(@types/node@25.3.3) - '@inquirer/rawlist': 4.1.11(@types/node@25.3.3) - '@inquirer/search': 3.2.2(@types/node@25.3.3) - '@inquirer/select': 4.4.2(@types/node@25.3.3) + '@types/node': 25.3.5 + + '@inquirer/prompts@7.10.1(@types/node@25.3.5)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@25.3.5) + '@inquirer/confirm': 5.1.21(@types/node@25.3.5) + '@inquirer/editor': 4.2.23(@types/node@25.3.5) + '@inquirer/expand': 4.0.23(@types/node@25.3.5) + '@inquirer/input': 4.3.1(@types/node@25.3.5) + '@inquirer/number': 3.0.23(@types/node@25.3.5) + '@inquirer/password': 4.0.23(@types/node@25.3.5) + '@inquirer/rawlist': 4.1.11(@types/node@25.3.5) + '@inquirer/search': 3.2.2(@types/node@25.3.5) + '@inquirer/select': 4.4.2(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 - - '@inquirer/prompts@8.3.0(@types/node@25.3.3)': - dependencies: - '@inquirer/checkbox': 5.1.0(@types/node@25.3.3) - '@inquirer/confirm': 6.0.8(@types/node@25.3.3) - '@inquirer/editor': 5.0.8(@types/node@25.3.3) - '@inquirer/expand': 5.0.8(@types/node@25.3.3) - '@inquirer/input': 5.0.8(@types/node@25.3.3) - '@inquirer/number': 4.0.8(@types/node@25.3.3) - '@inquirer/password': 5.0.8(@types/node@25.3.3) - '@inquirer/rawlist': 5.2.4(@types/node@25.3.3) - '@inquirer/search': 4.1.4(@types/node@25.3.3) - '@inquirer/select': 5.1.0(@types/node@25.3.3) + '@types/node': 25.3.5 + + '@inquirer/prompts@8.3.0(@types/node@25.3.5)': + dependencies: + '@inquirer/checkbox': 5.1.0(@types/node@25.3.5) + '@inquirer/confirm': 6.0.8(@types/node@25.3.5) + '@inquirer/editor': 5.0.8(@types/node@25.3.5) + '@inquirer/expand': 5.0.8(@types/node@25.3.5) + '@inquirer/input': 5.0.8(@types/node@25.3.5) + '@inquirer/number': 4.0.8(@types/node@25.3.5) + '@inquirer/password': 5.0.8(@types/node@25.3.5) + '@inquirer/rawlist': 5.2.4(@types/node@25.3.5) + '@inquirer/search': 4.1.4(@types/node@25.3.5) + '@inquirer/select': 5.1.0(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/rawlist@4.1.11(@types/node@25.3.3)': + '@inquirer/rawlist@4.1.11(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) + '@inquirer/type': 3.0.10(@types/node@25.3.5) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/rawlist@5.2.4(@types/node@25.3.3)': + '@inquirer/rawlist@5.2.4(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/search@3.2.2(@types/node@25.3.3)': + '@inquirer/search@3.2.2(@types/node@25.3.5)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/type': 3.0.10(@types/node@25.3.5) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/search@4.1.4(@types/node@25.3.3)': + '@inquirer/search@4.1.4(@types/node@25.3.5)': dependencies: - '@inquirer/core': 11.1.5(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/select@4.4.2(@types/node@25.3.3)': + '@inquirer/select@4.4.2(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.3.3) + '@inquirer/core': 10.3.2(@types/node@25.3.5) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.3.3) + '@inquirer/type': 3.0.10(@types/node@25.3.5) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/select@5.1.0(@types/node@25.3.3)': + '@inquirer/select@5.1.0(@types/node@25.3.5)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@25.3.3) + '@inquirer/core': 11.1.5(@types/node@25.3.5) '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@25.3.3) + '@inquirer/type': 4.0.3(@types/node@25.3.5) optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/type@3.0.10(@types/node@25.3.3)': + '@inquirer/type@3.0.10(@types/node@25.3.5)': optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 - '@inquirer/type@4.0.3(@types/node@25.3.3)': + '@inquirer/type@4.0.3(@types/node@25.3.5)': optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -3487,14 +3487,17 @@ snapshots: '@actions/github': 7.0.0 commander: 14.0.3 - '@nanoforge-dev/loader-client@1.2.0': + '@nanoforge-dev/loader-client@1.3.0': dependencies: - '@nanoforge-dev/loader-website': 1.1.0 + '@nanoforge-dev/loader-website': 1.2.0 bun: 1.3.10 + commander: 14.0.3 - '@nanoforge-dev/loader-server@1.1.0': {} + '@nanoforge-dev/loader-server@1.2.0': + dependencies: + commander: 14.0.3 - '@nanoforge-dev/loader-website@1.1.0': {} + '@nanoforge-dev/loader-website@1.2.0': {} '@nanoforge-dev/schematics@1.2.0(chokidar@5.0.0)': dependencies: @@ -3503,16 +3506,16 @@ snapshots: transitivePeerDependencies: - chokidar - '@nanoforge-dev/utils-eslint-config@1.0.2(@types/eslint@9.6.1)(eslint@10.0.2(jiti@2.6.1))(prettier@3.8.1)(typescript@5.9.3)': + '@nanoforge-dev/utils-eslint-config@1.0.2(@types/eslint@9.6.1)(eslint@10.0.3(jiti@2.6.1))(prettier@3.8.1)(typescript@5.9.3)': dependencies: - '@eslint/js': 9.39.3 + '@eslint/js': 9.39.4 '@favware/cliff-jumper': 6.0.0 - eslint-config-prettier: 10.1.8(eslint@10.0.2(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@10.0.3(jiti@2.6.1)) eslint-formatter-pretty: 7.0.0 - eslint-plugin-format: 1.5.0(eslint@10.0.2(jiti@2.6.1)) - eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(prettier@3.8.1) + eslint-plugin-format: 1.5.0(eslint@10.0.3(jiti@2.6.1)) + eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)))(eslint@10.0.3(jiti@2.6.1))(prettier@3.8.1) globals: 16.5.0 - typescript-eslint: 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) + typescript-eslint: 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - '@types/eslint' - eslint @@ -3849,7 +3852,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.3.3': + '@types/node@25.3.5': dependencies: undici-types: 7.18.2 @@ -3857,19 +3860,19 @@ snapshots: '@types/through@0.0.33': dependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 '@types/validator@13.15.10': {} - '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.56.1 - '@typescript-eslint/type-utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.56.1 - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -3877,14 +3880,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/types': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.56.1 debug: 4.4.3 - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -3907,13 +3910,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -3936,13 +3939,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.2(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/types': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -3952,7 +3955,7 @@ snapshots: '@typescript-eslint/types': 8.56.1 eslint-visitor-keys: 5.0.1 - '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.18 @@ -3964,7 +3967,7 @@ snapshots: obug: 2.1.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.18(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2) + vitest: 4.0.18(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2) '@vitest/expect@4.0.18': dependencies: @@ -3975,13 +3978,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2))': + '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2) + vite: 7.3.1(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2) '@vitest/pretty-format@4.0.18': dependencies: @@ -4196,9 +4199,9 @@ snapshots: conventional-commits-parser: 6.3.0 meow: 13.2.0 - cosmiconfig-typescript-loader@6.2.0(@types/node@25.3.3)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): + cosmiconfig-typescript-loader@6.2.0(@types/node@25.3.5)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): dependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 cosmiconfig: 9.0.1(typescript@5.9.3) jiti: 2.6.1 typescript: 5.9.3 @@ -4287,9 +4290,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@10.0.2(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)): dependencies: - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) eslint-formatter-pretty@7.0.0: dependencies: @@ -4302,39 +4305,39 @@ snapshots: string-width: 8.2.0 supports-hyperlinks: 4.4.0 - eslint-formatting-reporter@0.0.0(eslint@10.0.2(jiti@2.6.1)): + eslint-formatting-reporter@0.0.0(eslint@10.0.3(jiti@2.6.1)): dependencies: - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) prettier-linter-helpers: 1.0.1 eslint-parser-plain@0.1.1: {} - eslint-plugin-format@1.5.0(eslint@10.0.2(jiti@2.6.1)): + eslint-plugin-format@1.5.0(eslint@10.0.3(jiti@2.6.1)): dependencies: '@dprint/formatter': 0.5.1 '@dprint/markdown': 0.21.1 '@dprint/toml': 0.7.0 - eslint: 10.0.2(jiti@2.6.1) - eslint-formatting-reporter: 0.0.0(eslint@10.0.2(jiti@2.6.1)) + eslint: 10.0.3(jiti@2.6.1) + eslint-formatting-reporter: 0.0.0(eslint@10.0.3(jiti@2.6.1)) eslint-parser-plain: 0.1.1 ohash: 2.0.11 oxfmt: 0.35.0 prettier: 3.8.1 synckit: 0.11.12 - eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.0.2(jiti@2.6.1)))(eslint@10.0.2(jiti@2.6.1))(prettier@3.8.1): + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.0.3(jiti@2.6.1)))(eslint@10.0.3(jiti@2.6.1))(prettier@3.8.1): dependencies: - eslint: 10.0.2(jiti@2.6.1) + eslint: 10.0.3(jiti@2.6.1) prettier: 3.8.1 prettier-linter-helpers: 1.0.1 synckit: 0.11.12 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@10.0.2(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@10.0.3(jiti@2.6.1)) eslint-rule-docs@1.1.235: {} - eslint-scope@9.1.1: + eslint-scope@9.1.2: dependencies: '@types/esrecurse': 4.3.1 '@types/estree': 1.0.8 @@ -4345,14 +4348,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.0.2(jiti@2.6.1): + eslint@10.0.3(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.2(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.2 - '@eslint/config-helpers': 0.5.2 - '@eslint/core': 1.1.0 - '@eslint/plugin-kit': 0.6.0 + '@eslint/config-array': 0.23.3 + '@eslint/config-helpers': 0.5.3 + '@eslint/core': 1.1.1 + '@eslint/plugin-kit': 0.6.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -4361,9 +4364,9 @@ snapshots: cross-spawn: 7.0.6 debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 9.1.1 + eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 - espree: 11.1.1 + espree: 11.2.0 esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -4382,7 +4385,7 @@ snapshots: transitivePeerDependencies: - supports-color - espree@11.1.1: + espree@11.2.0: dependencies: acorn: 8.16.0 acorn-jsx: 5.3.2(acorn@8.16.0) @@ -5139,13 +5142,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3))(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 10.0.2(jiti@2.6.1) + '@typescript-eslint/utils': 8.56.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) + eslint: 10.0.3(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -5176,7 +5179,7 @@ snapshots: validator@13.15.26: {} - vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2): + vite@7.3.1(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) @@ -5185,15 +5188,15 @@ snapshots: rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 fsevents: 2.3.3 jiti: 2.6.1 yaml: 2.8.2 - vitest@4.0.18(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2): + vitest@4.0.18(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2)) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -5210,10 +5213,10 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(yaml@2.8.2) + vite: 7.3.1(@types/node@25.3.5)(jiti@2.6.1)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.3.5 transitivePeerDependencies: - jiti - less diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ed4014d..c5e8aec 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,5 @@ catalogs: build: - dotenv: ^17.3.1 tsup: ^8.5.1 typescript: ^5.9.3 ci: @@ -18,23 +17,24 @@ catalogs: node-emoji: ^2.2.0 ora: ^9.3.0 core: - '@types/node': ^25.3.3 + '@types/node': ^25.3.5 bun: ^1.3.10 libs: chokidar: ^5.0.0 class-transformer: ^0.5.1 class-validator: ^0.15.1 + dotenv: ^17.3.1 rc9: ^3.0.0 reflect-metadata: ^0.2.2 lint: '@nanoforge-dev/utils-eslint-config': ^1.0.2 '@nanoforge-dev/utils-prettier-config': ^1.0.2 '@trivago/prettier-plugin-sort-imports': ^6.0.2 - eslint: ^10.0.2 + eslint: ^10.0.3 prettier: ^3.8.1 loader: - '@nanoforge-dev/loader-client': ^1.2.0 - '@nanoforge-dev/loader-server': ^1.1.0 + '@nanoforge-dev/loader-client': ^1.3.0 + '@nanoforge-dev/loader-server': ^1.2.0 schematics: '@angular-devkit/schematics': ^21.2.1 '@angular-devkit/schematics-cli': ^21.2.1 diff --git a/src/action/actions/start.action.ts b/src/action/actions/start.action.ts index 44a9355..3c0e6d1 100644 --- a/src/action/actions/start.action.ts +++ b/src/action/actions/start.action.ts @@ -1,4 +1,5 @@ -import { join } from "path"; +import dotenv from "dotenv"; +import { join, resolve } from "path"; import { type Config } from "@lib/config"; import { @@ -18,17 +19,16 @@ import { getConfig } from "~/action/common/config"; import { AbstractAction, type HandleResult } from "../abstract.action"; -interface PortOptions { - clientPort: string; - gameExposurePort?: string; - serverPort?: string; -} - interface SSLOptions { cert: string; key: string; } +interface FullEnv { + client: Record; + server: Record; +} + export class StartAction extends AbstractAction { protected startMessage = Messages.START_START; protected successMessage = Messages.START_SUCCESS; @@ -38,23 +38,15 @@ export class StartAction extends AbstractAction { const directory = getDirectoryInput(options); const config = await getConfig(options, directory); const watch = getWatchInput(options); - const ports = this.resolvePorts(options, config); + const port = getStringInputWithDefault(options, "port", config.client.port); const ssl = this.resolveSSL(options); - const tasks = this.buildStartTasks(config, directory, watch, ports, ssl); + const tasks = this.buildStartTasks(config, directory, watch, port, ssl); await Promise.all(tasks); return { keepAlive: true }; } - private resolvePorts(options: Input, config: Config): PortOptions { - return { - clientPort: getStringInputWithDefault(options, "clientPort", config.client.port), - gameExposurePort: getStringInput(options, "gameExposurePort"), - serverPort: getStringInput(options, "serverPort"), - }; - } - private resolveSSL(options: Input): SSLOptions | undefined { const cert = getStringInput(options, "cert"); const key = getStringInput(options, "key"); @@ -74,16 +66,17 @@ export class StartAction extends AbstractAction { config: Config, directory: string, watch: boolean, - ports: PortOptions, + port: string, ssl?: SSLOptions, ): Promise[] { + const env = this.parseEnv(directory); const tasks: Promise[] = []; if (config.server.enable) { - tasks.push(this.startServer(directory, config.server.runtime.dir, watch, ports.serverPort)); + tasks.push(this.startServer(directory, config, { watch }, env)); } - tasks.push(this.startClient(directory, config, watch, ports, ssl)); + tasks.push(this.startClient(directory, config, { watch, port, ssl }, env)); return tasks; } @@ -91,74 +84,111 @@ export class StartAction extends AbstractAction { private async startClient( directory: string, config: Config, - watch: boolean, - ports: PortOptions, - ssl?: SSLOptions, + options: { watch: boolean; port: string; ssl?: SSLOptions }, + env: FullEnv, ): Promise { const loaderPath = getModulePath("@nanoforge-dev/loader-client/package.json", true); - const gameDir = config.client.runtime.dir; - const env = this.buildClientEnv(directory, gameDir, watch, config, ports, ssl); - await this.runLoader("Client", loaderPath, env); + const params = this.buildClientParams(directory, config, options); + await this.runLoader("Client", loaderPath, params, env.client); } - private buildClientEnv( + private async startServer( directory: string, - gameDir: string, - watch: boolean, config: Config, - ports: PortOptions, - ssl?: SSLOptions, - ): Record { - const env: Record = { - PORT: ports.clientPort, - GAME_DIR: getCwd(join(directory, gameDir)), - }; + options: { watch: boolean }, + env: FullEnv, + ): Promise { + const loaderPath = getModulePath("@nanoforge-dev/loader-server/package.json", true); - if (ports.gameExposurePort) { - env["GAME_EXPOSURE_PORT"] = ports.gameExposurePort; - } + const params = this.buildServerParams(directory, config, options); + await this.runLoader("Server", loaderPath, params, env.server); + } - if (watch) { - env["WATCH"] = "true"; + private buildClientParams( + directory: string, + config: Config, + options: { watch: boolean; port: string; ssl?: SSLOptions }, + ): string[] { + const params: Record = { + "-d": getCwd(join(directory, config.client.runtime.dir)), + "-p": options.port, + }; + if (options.watch) params["--watch"] = true; + + if (options.watch) { + params["--watch"] = true; if (config.server.enable) { - env["WATCH_SERVER_GAME_DIR"] = getCwd(join(directory, config.server.runtime.dir)); + params["--watch-server-dir"] = getCwd(join(directory, config.server.runtime.dir)); } } - if (ssl) { - env["CERT"] = ssl.cert; - env["KEY"] = ssl.key; + if (options.ssl) { + params["--cert"] = options.ssl.cert; + params["--key"] = options.ssl.key; } - return env; + return this.buildParams(params); } - private async startServer( + private buildServerParams( directory: string, - gameDir: string, - watch: boolean, - port?: string, - ): Promise { - const loaderPath = getModulePath("@nanoforge-dev/loader-server/package.json", true); + config: Config, + options: { watch: boolean }, + ): string[] { + const params: Record = { + "-d": getCwd(join(directory, config.server.runtime.dir)), + }; + if (options.watch) params["--watch"] = true; + + return this.buildParams(params); + } + + private buildParams(params: Record): string[] { + return Object.entries(params) + .map(([key, value]) => (typeof value === "string" ? [key, value] : [key])) + .flat(); + } - const env: Record = { - GAME_DIR: getCwd(join(directory, gameDir)), + private parseEnv(dir: string): FullEnv { + const prefix = "NANOFORGE_"; + const clientPrefix = `${prefix}CLIENT_`; + const serverPrefix = `${prefix}SERVER_`; + + const rawEnv = { + ...process.env, }; - if (port) env["PORT"] = port; - if (watch) env["WATCH"] = "true"; + dotenv.config({ + path: resolve(getCwd(join(dir, ".env"))), + processEnv: rawEnv, + }); + const baseEnv = Object.entries(rawEnv).filter( + ([key, value]) => key.startsWith(prefix) && !!value, + ) as [string, string][]; - await this.runLoader("Server", loaderPath, env); + return { + client: Object.fromEntries( + baseEnv + .filter(([key]) => !key.startsWith(serverPrefix)) + .map(([key, value]) => [key.replace(clientPrefix, prefix), value]), + ), + server: Object.fromEntries( + baseEnv + .filter(([key]) => !key.startsWith(clientPrefix)) + .map(([key, value]) => [key.replace(serverPrefix, prefix), value]), + ), + }; } private async runLoader( name: string, directory: string, + params: string[], env: Record, ): Promise { await runSafe(async () => { const packageManager = await PackageManagerFactory.find(directory); - await packageManager.run(name, directory, "start", env, [], true); + await packageManager.run(name, directory, "start", params, env, [], true); }); } } diff --git a/src/command/commands/start.command.ts b/src/command/commands/start.command.ts index 1b1a8cc..6d1aecc 100644 --- a/src/command/commands/start.command.ts +++ b/src/command/commands/start.command.ts @@ -7,9 +7,7 @@ import { AbstractCommand } from "../abstract.command"; interface StartOptions { directory?: string; config?: string; - clientPort?: string; - gameExposurePort?: string; - serverPort?: string; + port?: string; watch?: boolean; cert?: string; key?: string; @@ -22,12 +20,7 @@ export class StartCommand extends AbstractCommand { .description("start your game") .option("-d, --directory [directory]", "specify the directory of your project") .option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME) - .option( - "-p, --client-port [clientPort]", - "specify the port of the loader (the website to load the game)", - ) - .option("--game-exposure-port [gameExposurePort]", "specify the port of the game exposure") - .option("--server-port [serverPort]", "specify the port of the server") + .option("-p, --port [port]", "specify the port of the loader (the website to load the game)") .option("--watch", "run app in watching mode", false) .option("--cert [cert]", "path to the SSL certificate for HTTPS") .option("--key [key]", "path to the SSL key for HTTPS") @@ -35,9 +28,7 @@ export class StartCommand extends AbstractCommand { const options = AbstractCommand.mapToInput({ directory: rawOptions.directory, config: rawOptions.config, - clientPort: rawOptions.clientPort, - gameExposurePort: rawOptions.gameExposurePort, - serverPort: rawOptions.serverPort, + port: rawOptions.port, watch: rawOptions.watch, cert: rawOptions.cert, key: rawOptions.key, diff --git a/src/lib/config/config-defaults.ts b/src/lib/config/config-defaults.ts index b193e02..2f21c06 100644 --- a/src/lib/config/config-defaults.ts +++ b/src/lib/config/config-defaults.ts @@ -6,7 +6,6 @@ export const CONFIG_DEFAULTS: Config = { initFunctions: true, client: { port: "3000", - gameExposurePort: "3001", build: { entryFile: "client/main.ts", outDir: ".nanoforge/client", @@ -17,7 +16,6 @@ export const CONFIG_DEFAULTS: Config = { }, server: { enable: false, - port: "3002", build: { entryFile: "server/main.ts", outDir: ".nanoforge/server", diff --git a/src/lib/config/config.type.ts b/src/lib/config/config.type.ts index f77f794..657cacf 100644 --- a/src/lib/config/config.type.ts +++ b/src/lib/config/config.type.ts @@ -25,10 +25,6 @@ export class ClientConfig { @IsPort() port!: string; - @Expose() - @IsPort() - gameExposurePort!: string; - @Expose() @Type(() => BuildConfig) @ValidateNested() @@ -45,10 +41,6 @@ export class ServerConfig { @IsBoolean() enable!: boolean; - @Expose() - @IsPort() - port!: string; - @Expose() @Type(() => BuildConfig) @ValidateNested() diff --git a/src/lib/package-manager/package-manager-commands.ts b/src/lib/package-manager/package-manager-commands.ts index d5b4f2c..ddf57f7 100644 --- a/src/lib/package-manager/package-manager-commands.ts +++ b/src/lib/package-manager/package-manager-commands.ts @@ -5,6 +5,7 @@ export interface PackageManagerCommands { remove: string; exec: string; run: string; + runArgsFlag?: string; build?: string; runFile?: string; saveFlag: string; diff --git a/src/lib/package-manager/package-manager-configs.ts b/src/lib/package-manager/package-manager-configs.ts index 496f6d3..f8f2ba3 100644 --- a/src/lib/package-manager/package-manager-configs.ts +++ b/src/lib/package-manager/package-manager-configs.ts @@ -44,6 +44,7 @@ export const PM_CONFIGS: Record< remove: "uninstall", exec: "exec", run: "run", + runArgsFlag: "--", saveFlag: "--save", saveDevFlag: "--save-dev", silentFlag: "--silent", diff --git a/src/lib/package-manager/package-manager.ts b/src/lib/package-manager/package-manager.ts index 1e4a1fb..466452d 100644 --- a/src/lib/package-manager/package-manager.ts +++ b/src/lib/package-manager/package-manager.ts @@ -84,6 +84,7 @@ export class PackageManager { name: string, directory: string, script: string, + params: string[], env: Record = {}, flags: string[] = [], silent = false, @@ -91,7 +92,7 @@ export class PackageManager { console.info(Messages.START_PART_IN_PROGRESS(name)); try { - const args = this.buildRunArgs(script, flags, silent); + const args = this.buildRunArgs(script, params, flags, silent); await this.exec(args, directory, { env, listeners: { @@ -171,11 +172,18 @@ export class PackageManager { } } - private buildRunArgs(script: string, flags: string[], silent: boolean): string[] { + private buildRunArgs( + script: string, + params: string[], + flags: string[], + silent: boolean, + ): string[] { const args = [...flags, this.commands.run]; if (silent) args.push(this.commands.silentFlag); args.push(script); - return args; + if (params.length === 0) return args; + if (this.commands.runArgsFlag) args.push(this.commands.runArgsFlag); + return args.concat(params); } private exec(