diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..d4a10b20 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,52 @@ +{ + "extends": "zardoy", + "rules": { + // perf + "import/no-deprecated": "off", + // --- + "@typescript-eslint/prefer-nullish-coalescing": "off", + "@typescript-eslint/naming-convention": "off", + "prefer-template": "off", + // intentional: improve readability in some cases + "no-else-return": "off", + "@typescript-eslint/padding-line-between-statements": "off", + "arrow-body-style": "off", + "unicorn/prefer-ternary": "off", + "unicorn/switch-case-braces": "off", + "@typescript-eslint/consistent-type-definitions": "off", + "unicorn/explicit-length-check": "off", + "unicorn/prefer-dom-node-append": "off", + "typescript-eslint/no-confusing-void-expression": "off", + "unicorn/no-lonely-if": "off", + "no-multi-assign": "off", + "sonarjs/no-duplicate-string": "off", + "new-cap": "off", + "unicorn/consistent-destructuring": "off", + "unicorn/no-await-expression-member": "off", + "unicorn/prefer-add-event-listener": "off", + "unicorn/prefer-top-level-await": "off", + "default-case": "off", + // I guess it would better to fix + "node/prefer-global/buffer": "off", + "unicorn/prefer-optional-catch-binding": "off", // still useful for debugging + "no-alert": "off", // todo once replaced with ui, enable + "@typescript-eslint/restrict-plus-operands": "off", + // --- + "@typescript-eslint/no-throw-literal": "off", // disabling because of "rule expansion" + "no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "off", + "import/no-extraneous-dependencies": "off", + "@typescript-eslint/ban-types": "off", + "unicorn/prefer-query-selector": "off", + "@typescript-eslint/dot-notation": "off", // trick prop type-checking + "@typescript-eslint/consistent-type-imports": "off", + "no-negated-condition": "off", + "@typescript-eslint/no-require-imports": "off", + "unicorn/prefer-number-properties": "off", + "@typescript-eslint/no-confusing-void-expression": "off", + // needs to be fixed actually + "@typescript-eslint/no-floating-promises": "warn", + "no-async-promise-executor": "off", + "no-bitwise": "off" + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c132fa56..c53d6061 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,7 @@ jobs: - name: Install pnpm run: npm i -g pnpm - run: pnpm install + - run: pnpm lint - run: pnpm check-build - run: nohup pnpm prod-start & - run: nohup node cypress/minecraft-server.mjs & diff --git a/cypress/integration/index.spec.ts b/cypress/integration/index.spec.ts index c4f23917..3c184b46 100644 --- a/cypress/integration/index.spec.ts +++ b/cypress/integration/index.spec.ts @@ -43,6 +43,7 @@ it('Loads & renders singleplayer', () => { localServerOptions: { generation: { name: 'superflat', + // eslint-disable-next-line unicorn/numeric-separators-style options: { seed: 250869072 } }, }, diff --git a/package.json b/package.json index f43118dd..69523bae 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "test:cypress": "cypress run", "test:e2e": "start-test http-get://localhost:8080 test:cypress", "prod-start": "node server.js", - "postinstall": "node scripts/gen-texturepack-files.mjs" + "postinstall": "node scripts/gen-texturepack-files.mjs", + "lint": "eslint \"{src,cypress}/**/*.{ts,js,jsx,tsx}\"" }, "keywords": [ "prismarine", @@ -61,6 +62,8 @@ "crypto-browserify": "^3.12.0", "cypress": "^9.5.4", "cypress-esbuild-preprocessor": "^1.0.2", + "eslint": "^8.50.0", + "eslint-config-zardoy": "^0.2.17", "events": "^3.3.0", "filesize": "^10.0.12", "http-browserify": "^1.7.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8926a7f3..49270a55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,6 +133,12 @@ importers: cypress-esbuild-preprocessor: specifier: ^1.0.2 version: 1.0.2 + eslint: + specifier: ^8.50.0 + version: 8.50.0 + eslint-config-zardoy: + specifier: ^0.2.17 + version: 0.2.17(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0)(typescript@5.2.2) events: specifier: ^3.3.0 version: 3.3.0 @@ -283,7 +289,7 @@ importers: version: 16.0.0 standard: specifier: ^17.0.0 - version: 17.0.0 + version: 17.0.0(@typescript-eslint/parser@6.7.3) webpack: specifier: ^5.10.2 version: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) @@ -1847,6 +1853,16 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.50.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.50.0 + eslint-visitor-keys: 3.4.3 + dev: true + /@eslint-community/regexpp@4.8.0: resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -1874,6 +1890,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@eslint/js@8.50.0: + resolution: {integrity: sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} dev: true @@ -1895,6 +1916,17 @@ packages: - supports-color dev: true + /@humanwhocodes/config-array@0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4(supports-color@8.1.1) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -2690,6 +2722,10 @@ packages: rollup: 2.79.1 dev: false + /@rushstack/eslint-patch@1.4.0: + resolution: {integrity: sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==} + dev: true + /@sideway/address@4.1.4: resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} dependencies: @@ -2842,6 +2878,10 @@ packages: /@types/node@20.6.4: resolution: {integrity: sha512-nU6d9MPY0NBUMiE/nXd2IIoC4OLvsLpwAjheoAeuzgvDZA1Cb10QYg+91AF6zQiKWRN5i1m07x6sMe0niBznoQ==} + /@types/normalize-package-data@2.4.2: + resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==} + dev: true + /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: false @@ -2881,6 +2921,10 @@ packages: /@types/scheduler@0.16.3: resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + /@types/semver@7.5.3: + resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==} + dev: true + /@types/sinonjs__fake-timers@8.1.1: resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} @@ -2920,6 +2964,180 @@ packages: '@types/node': 20.5.7 optional: true + /@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.8.0 + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.1.0 + '@typescript-eslint/type-utils': 6.1.0(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.1.0 + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.50.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + natural-compare-lite: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.7.3 + '@typescript-eslint/types': 6.7.3 + '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.7.3 + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.50.0 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.1.0: + resolution: {integrity: sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/visitor-keys': 6.1.0 + dev: true + + /@typescript-eslint/scope-manager@6.7.3: + resolution: {integrity: sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.7.3 + '@typescript-eslint/visitor-keys': 6.7.3 + dev: true + + /@typescript-eslint/type-utils@6.1.0(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.2.2) + '@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.2.2) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.50.0 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.1.0: + resolution: {integrity: sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/types@6.7.3: + resolution: {integrity: sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.1.0(typescript@5.2.2): + resolution: {integrity: sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/visitor-keys': 6.1.0 + debug: 4.3.4(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@6.7.3(typescript@5.2.2): + resolution: {integrity: sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.7.3 + '@typescript-eslint/visitor-keys': 6.7.3 + debug: 4.3.4(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.1.0(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.3 + '@typescript-eslint/scope-manager': 6.1.0 + '@typescript-eslint/types': 6.1.0 + '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.2.2) + eslint: 8.50.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.1.0: + resolution: {integrity: sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.1.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@6.7.3: + resolution: {integrity: sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.7.3 + eslint-visitor-keys: 3.4.3 + dev: true + /@webassemblyjs/ast@1.11.6: resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} dependencies: @@ -3330,6 +3548,11 @@ packages: is-string: 1.0.7 dev: true + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + /array.prototype.findlastindex@1.2.2: resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==} engines: {node: '>= 0.4'} @@ -3826,7 +4049,6 @@ packages: /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - dev: false /builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} @@ -3996,6 +4218,13 @@ packages: resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} dev: false + /clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -4163,6 +4392,10 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + /confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: true + /console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: true @@ -4651,6 +4884,13 @@ packages: randombytes: 2.1.0 dev: true + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + /discontinuous-range@1.0.0: resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==} @@ -5053,6 +5293,15 @@ packages: source-map: 0.6.1 dev: true + /eslint-config-prettier@8.10.0(eslint@8.50.0): + resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.50.0 + dev: true + /eslint-config-standard-jsx@11.0.0(eslint-plugin-react@7.33.2)(eslint@8.48.0): resolution: {integrity: sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==} peerDependencies: @@ -5072,11 +5321,85 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.48.0 - eslint-plugin-import: 2.28.1(eslint@8.48.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint@8.48.0) eslint-plugin-n: 15.7.0(eslint@8.48.0) eslint-plugin-promise: 6.1.1(eslint@8.48.0) dev: true + /eslint-config-xo-react@0.27.0(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0): + resolution: {integrity: sha512-wiV215xQIn71XZyyVfaOXHaFpR1B14IJttwOjMi/eqUK1s+ojJdHr7eHqTLaGUfh6FKgWha1QNwePlIXx7mBUg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=8.6.0' + eslint-plugin-react: '>=7.29.0' + eslint-plugin-react-hooks: '>=4.3.0' + dependencies: + eslint: 8.50.0 + eslint-plugin-react: 7.33.2(eslint@8.50.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.50.0) + dev: true + + /eslint-config-xo-typescript@1.0.1(@typescript-eslint/eslint-plugin@6.1.0)(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-vPQssnRSUgBFOEfB/KY12CXwltwFSn4RSCfa+w7gjBC2PFQ7Yfgmyei+1XUZ3K+8LRGef2NMJUcxts7PldhDjg==} + engines: {node: '>=16'} + peerDependencies: + '@typescript-eslint/eslint-plugin': '>=6.0.0' + '@typescript-eslint/parser': '>=6.0.0' + eslint: '>=8.0.0' + typescript: '>=4.7' + dependencies: + '@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + eslint: 8.50.0 + typescript: 5.2.2 + dev: true + + /eslint-config-xo@0.43.1(eslint@8.50.0): + resolution: {integrity: sha512-azv1L2PysRA0NkZOgbndUpN+581L7wPqkgJOgxxw3hxwXAbJgD6Hqb/SjHRiACifXt/AvxCzE/jIKFAlI7XjvQ==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=8.27.0' + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.50.0 + dev: true + + /eslint-config-zardoy@0.2.17(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0)(typescript@5.2.2): + resolution: {integrity: sha512-d31WsjyVSQqHbzTpBSmH96+nw5gwY2yhDbZatU89gr+U8ou1FRUkJSApYJUgmcINt8AQocj1RDDAVYmVSILZgQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + eslint: ^8.5.0 + eslint-plugin-vue: ^8.4.1 + typescript: ^4.5.2 + vue-eslint-parser: ^8.2.0 + peerDependenciesMeta: + eslint-plugin-vue: + optional: true + vue-eslint-parser: + optional: true + dependencies: + '@rushstack/eslint-patch': 1.4.0 + '@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + eslint: 8.50.0 + eslint-config-prettier: 8.10.0(eslint@8.50.0) + eslint-config-xo: 0.43.1(eslint@8.50.0) + eslint-config-xo-react: 0.27.0(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0) + eslint-config-xo-typescript: 1.0.1(@typescript-eslint/eslint-plugin@6.1.0)(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.50.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.7.3)(eslint@8.50.0) + eslint-plugin-node: 11.1.0(eslint@8.50.0) + eslint-plugin-sonarjs: 0.19.0(eslint@8.50.0) + eslint-plugin-unicorn: 48.0.0(eslint@8.50.0) + typescript: 5.2.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - eslint-plugin-react + - eslint-plugin-react-hooks + - supports-color + dev: true + /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: @@ -5087,7 +5410,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(eslint-import-resolver-node@0.3.9)(eslint@8.48.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.48.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -5108,6 +5431,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) debug: 3.2.7(supports-color@8.1.1) eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 @@ -5115,6 +5439,46 @@ packages: - supports-color dev: true + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.50.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + debug: 3.2.7(supports-color@8.1.1) + eslint: 8.50.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es@3.0.1(eslint@8.50.0): + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.50.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: true + /eslint-plugin-es@4.1.0(eslint@8.48.0): resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} engines: {node: '>=8.10.0'} @@ -5126,7 +5490,51 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.28.1(eslint@8.48.0): + /eslint-plugin-eslint-comments@3.2.0(eslint@8.50.0): + resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} + engines: {node: '>=6.5.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + escape-string-regexp: 1.0.5 + eslint: 8.50.0 + ignore: 5.2.4 + dev: true + + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.7.3)(eslint@8.50.0): + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) + array-includes: 3.1.6 + array.prototype.flat: 1.3.1 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7(supports-color@8.1.1) + doctrine: 2.1.0 + eslint: 8.50.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.50.0) + has: 1.0.3 + is-core-module: 2.13.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.7 + resolve: 1.22.4 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.3)(eslint@8.48.0): resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} engines: {node: '>=4'} peerDependencies: @@ -5136,6 +5544,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: + '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2) array-includes: 3.1.6 array.prototype.findlastindex: 1.2.2 array.prototype.flat: 1.3.1 @@ -5144,7 +5553,7 @@ packages: doctrine: 2.1.0 eslint: 8.48.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(eslint-import-resolver-node@0.3.9)(eslint@8.48.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.48.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -5177,6 +5586,21 @@ packages: semver: 7.5.4 dev: true + /eslint-plugin-node@11.1.0(eslint@8.50.0): + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + dependencies: + eslint: 8.50.0 + eslint-plugin-es: 3.0.1(eslint@8.50.0) + eslint-utils: 2.1.0 + ignore: 5.2.4 + minimatch: 3.1.2 + resolve: 1.22.4 + semver: 6.3.1 + dev: true + /eslint-plugin-promise@6.1.1(eslint@8.48.0): resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5186,6 +5610,15 @@ packages: eslint: 8.48.0 dev: true + /eslint-plugin-react-hooks@4.6.0(eslint@8.50.0): + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 8.50.0 + dev: true + /eslint-plugin-react@7.33.2(eslint@8.48.0): resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} engines: {node: '>=4'} @@ -5211,6 +5644,64 @@ packages: string.prototype.matchall: 4.0.8 dev: true + /eslint-plugin-react@7.33.2(eslint@8.50.0): + resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + array-includes: 3.1.6 + array.prototype.flatmap: 1.3.1 + array.prototype.tosorted: 1.1.1 + doctrine: 2.1.0 + es-iterator-helpers: 1.0.14 + eslint: 8.50.0 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.7 + object.fromentries: 2.0.6 + object.hasown: 1.1.3 + object.values: 1.1.7 + prop-types: 15.8.1 + resolve: 2.0.0-next.4 + semver: 6.3.1 + string.prototype.matchall: 4.0.8 + dev: true + + /eslint-plugin-sonarjs@0.19.0(eslint@8.50.0): + resolution: {integrity: sha512-6+s5oNk5TFtVlbRxqZN7FIGmjdPCYQKaTzFPmqieCmsU1kBYDzndTeQav0xtQNwZJWu5awWfTGe8Srq9xFOGnw==} + engines: {node: '>=14'} + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.50.0 + dev: true + + /eslint-plugin-unicorn@48.0.0(eslint@8.50.0): + resolution: {integrity: sha512-8fk/v3p1ro34JSVDBEmtOq6EEQRpMR0iTir79q69KnXFZ6DJyPkT3RAi+ZoTqhQMdDSpGh8BGR68ne1sP5cnAA==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.44.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) + ci-info: 3.8.0 + clean-regexp: 1.0.0 + eslint: 8.50.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + lodash: 4.17.21 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.5.4 + strip-indent: 3.0.0 + dev: true + /eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -5305,6 +5796,52 @@ packages: - supports-color dev: true + /eslint@8.50.0: + resolution: {integrity: sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) + '@eslint-community/regexpp': 4.8.0 + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.50.0 + '@humanwhocodes/config-array': 0.11.11 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4(supports-color@8.1.1) + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.21.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5527,6 +6064,17 @@ packages: /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -5908,6 +6456,13 @@ packages: dependencies: assert-plus: 1.0.0 + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -5989,6 +6544,18 @@ packages: dependencies: define-properties: 1.2.0 + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -6400,6 +6967,13 @@ packages: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} dev: true + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -7310,13 +7884,18 @@ packages: /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true - dev: false /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true @@ -7776,6 +8355,11 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + /merge@1.2.1: resolution: {integrity: sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==} dev: false @@ -7830,6 +8414,11 @@ packages: dom-walk: 0.1.2 dev: false + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + /minecraft-assets@1.9.0: resolution: {integrity: sha512-KtvIRd9gcKlxbvrswGv1Ap9k7tVs//QW2ukp+8vJ28miYwkhUmYfjTZyElIG8KUXV/46wL2kDzLH8SJbXQ56Mg==} dev: true @@ -8071,6 +8660,10 @@ packages: stylis: 4.2.0 dev: false + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true @@ -8548,7 +9141,6 @@ packages: /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: false /pbkdf2@3.1.2: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} @@ -8641,6 +9233,11 @@ packages: find-up: 4.1.0 dev: true + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + /pngjs@3.4.0: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} @@ -9140,6 +9737,15 @@ packages: dependencies: loose-envify: 1.4.0 + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + /read-pkg@3.0.0: resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} engines: {node: '>=4'} @@ -9149,6 +9755,16 @@ packages: path-type: 3.0.0 dev: true + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.2 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + /readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} dependencies: @@ -9226,6 +9842,11 @@ packages: '@babel/runtime': 7.22.11 dev: false + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + /regexp.prototype.flags@1.5.0: resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} engines: {node: '>= 0.4'} @@ -9251,6 +9872,13 @@ packages: unicode-match-property-value-ecmascript: 2.1.0 dev: false + /regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + /regjsparser@0.9.1: resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} hasBin: true @@ -9966,7 +10594,7 @@ packages: xdg-basedir: 4.0.0 dev: true - /standard@17.0.0: + /standard@17.0.0(@typescript-eslint/parser@6.7.3): resolution: {integrity: sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true @@ -9974,7 +10602,7 @@ packages: eslint: 8.48.0 eslint-config-standard: 17.0.0(eslint-plugin-import@2.28.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.48.0) eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.33.2)(eslint@8.48.0) - eslint-plugin-import: 2.28.1(eslint@8.48.0) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint@8.48.0) eslint-plugin-n: 15.7.0(eslint@8.48.0) eslint-plugin-promise: 6.1.1(eslint@8.48.0) eslint-plugin-react: 7.33.2(eslint@8.48.0) @@ -10126,6 +10754,13 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -10403,6 +11038,15 @@ packages: utf8-byte-length: 1.0.4 dev: false + /ts-api-utils@1.0.3(typescript@5.2.2): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.2.2 + dev: true + /ts-easing@0.2.0: resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} dev: false @@ -10458,6 +11102,16 @@ packages: engines: {node: '>=6'} dev: true + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + /type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} diff --git a/src/browserfs.ts b/src/browserfs.ts index ed2f7eba..bac4d5dc 100644 --- a/src/browserfs.ts +++ b/src/browserfs.ts @@ -1,13 +1,13 @@ //@ts-check -import { fsState, loadSave } from './loadSave' +import { join } from 'path' +import { promisify } from 'util' +import fs from 'fs' import { oneOf } from '@zardoy/utils' import JSZip from 'jszip' -import { join } from 'path' +import * as browserfs from 'browserfs' import { options } from './optionsStorage' -import { promisify } from 'util' -import * as browserfs from 'browserfs' -import fs from 'fs' +import { fsState, loadSave } from './loadSave' import { installTexturePack, updateTexturePackInstalledState } from './texturePack' browserfs.install(window) @@ -15,7 +15,7 @@ browserfs.install(window) const deafultMountablePoints = { "/world": { fs: "LocalStorage" }, '/userData': { fs: 'IndexedDB' }, -}; +} browserfs.configure({ fs: 'MountableFileSystem', options: deafultMountablePoints, @@ -26,10 +26,9 @@ browserfs.configure({ export const forceCachedDataPaths = {} -//@ts-ignore +//@ts-expect-error fs.promises = new Proxy(Object.fromEntries(['readFile', 'writeFile', 'stat', 'mkdir', 'rmdir', 'unlink', 'rename', /* 'copyFile', */'readdir'].map(key => [key, promisify(fs[key])])), { - get(target, p, receiver) { - //@ts-ignore + get(target, p: string, receiver) { if (!target[p]) throw new Error(`Not implemented fs.promises.${p}`) return (...args) => { // browser fs bug: if path doesn't start with / dirname will return . which would cause infinite loop, so we need to normalize paths @@ -50,20 +49,20 @@ fs.promises = new Proxy(Object.fromEntries(['readFile', 'writeFile', 'stat', 'mk if (p === 'open' && fsState.isReadonly) { args[1] = 'r' // read-only, zipfs throw otherwise } - //@ts-ignore return target[p](...args) } } }) -//@ts-ignore +//@ts-expect-error fs.promises.open = async (...args) => { const fd = await promisify(fs.open)(...args) return { ...Object.fromEntries(['read', 'write', 'close'].map(x => [x, async (...args) => { - return await new Promise(resolve => { + return new Promise(resolve => { // todo it results in world corruption on interactions eg block placements if (x === 'write' && fsState.isReadonly) { - return resolve({ buffer: Buffer.from([]), bytesRead: 0 }) + resolve({ buffer: Buffer.from([]), bytesRead: 0 }) + return } fs[x](fd, ...args, (err, bytesRead, buffer) => { @@ -80,7 +79,7 @@ fs.promises.open = async (...args) => { // for debugging fd, filename: args[0], - close: () => { + async close() { return new Promise(resolve => { fs.close(fd, (err) => { if (err) { @@ -96,7 +95,7 @@ fs.promises.open = async (...args) => { // for testing purposes, todo move it to core patch const removeFileRecursiveSync = (path) => { - fs.readdirSync(path).forEach((file) => { + for (const file of fs.readdirSync(path)) { const curPath = join(path, file) if (fs.lstatSync(curPath).isDirectory()) { // recurse @@ -106,30 +105,26 @@ const removeFileRecursiveSync = (path) => { // delete file fs.unlinkSync(curPath) } - }) + } } window.removeFileRecursiveSync = removeFileRecursiveSync // todo it still doesnt clean the storage, need to debug export async function removeFileRecursiveAsync(path) { - try { - const files = await fs.promises.readdir(path); - for (const file of files) { - const curPath = join(path, file); - const stats = await fs.promises.stat(curPath); - if (stats.isDirectory()) { - // Recurse - await removeFileRecursiveAsync(curPath); - } else { - // Delete file - await fs.promises.unlink(curPath); - } + const files = await fs.promises.readdir(path) + for (const file of files) { + const curPath = join(path, file) + const stats = await fs.promises.stat(curPath) + if (stats.isDirectory()) { + // Recurse + await removeFileRecursiveAsync(curPath) + } else { + // Delete file + await fs.promises.unlink(curPath) } - await fs.promises.rmdir(path); - } catch (error) { - throw error; } + await fs.promises.rmdir(path) } @@ -181,9 +176,9 @@ export const openWorldDirectory = async (dragndropHandle?: FileSystemDirectoryHa const tryToDetectResourcePack = async (file: File | ArrayBuffer) => { const askInstall = async () => { return alert('ATM You can install texturepacks only via options menu. WIll be fixed') - if (confirm('Resource pack detected, do you want to install it?')) { - await installTexturePack(file) - } + // if (confirm('Resource pack detected, do you want to install it?')) { + // await installTexturePack(file) + // } } if (fs.existsSync('/world/pack.mcmeta')) { @@ -243,7 +238,7 @@ const openWorldZipInner = async (file: File | ArrayBuffer, name = file['name']) await loadSave() } else { const dirs = fs.readdirSync('/world') - let availableWorlds: string[] = [] + const availableWorlds: string[] = [] for (const dir of dirs) { if (fs.existsSync(`/world/${dir}/level.dat`)) { availableWorlds.push(dir) diff --git a/src/builtinCommands.ts b/src/builtinCommands.ts index 2168655b..197ebb00 100644 --- a/src/builtinCommands.ts +++ b/src/builtinCommands.ts @@ -1,6 +1,6 @@ -import JSZip from 'jszip' import fs from 'fs' import { join } from 'path' +import JSZip from 'jszip' import { fsState } from './loadSave' import { closeWan, openToWanAndCopyJoinLink } from './localServerMultiplayer' @@ -32,7 +32,7 @@ async function addFolderToZip(folderPath, zip, relativePath) { const exportWorld = async () => { // todo issue into chat warning if fs is writable! const zip = new JSZip() - let worldFolder: string = localServer.options.worldFolder + let {worldFolder} = localServer.options if (!worldFolder.startsWith('/')) worldFolder = `/${worldFolder}` await addFolderToZip(worldFolder, zip, '') @@ -64,21 +64,21 @@ const commands = [ }, { command: ['/publish', '/share'], - invoke: async () => { + async invoke() { const text = await openToWanAndCopyJoinLink(writeText) if (text) writeText(text) } }, { command: ['/close'], - invoke: () => { + invoke() { const text = closeWan() if (text) writeText(text) } }, { command: '/reset-world -y', - invoke: async () => { + async invoke() { if (fsState.inMemorySave) return // todo for testing purposes sessionStorage.oldData = localStorage @@ -90,7 +90,7 @@ const commands = [ }, { command: ['/save'], - invoke: () => { + invoke() { saveWorld() } } diff --git a/src/controls.ts b/src/controls.ts index 7b7017fa..1f573eea 100644 --- a/src/controls.ts +++ b/src/controls.ts @@ -1,12 +1,12 @@ //@ts-check import { Vec3 } from 'vec3' -import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal } from './globalState' import { proxy, subscribe } from 'valtio' import { ControMax } from 'contro-max/build/controMax' import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types' import { stringStartsWith } from 'contro-max/build/stringUtils' +import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal } from './globalState' import { reloadChunks } from './utils' // doesnt seem to work for now @@ -137,6 +137,7 @@ const onTriggerOrReleased = (command: Command, pressed: boolean) => { } if (stringStartsWith(command, 'general')) { // handle general commands + // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check switch (command) { case 'general.jump': bot.setControlState('jump', pressed) @@ -189,6 +190,7 @@ contro.on('trigger', ({ command }) => { onTriggerOrReleased(command, true) if (stringStartsWith(command, 'general')) { + // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check switch (command) { case 'general.inventory': document.exitPointerLock?.() @@ -225,7 +227,7 @@ document.addEventListener('keydown', (e) => { if (hardcodedPressedKeys.has('F3')) { // reload chunks if (e.code === 'KeyA') { - //@ts-ignore + //@ts-expect-error const loadedChunks = Object.entries(worldView.loadedChunks).filter(([, v]) => v).map(([key]) => key.split(',').map(Number)) for (const [x, z] of loadedChunks) { worldView.unloadChunk({ x, z }) diff --git a/src/downloadAndOpenFile.ts b/src/downloadAndOpenFile.ts index 0192ab4c..66e2cbd5 100644 --- a/src/downloadAndOpenFile.ts +++ b/src/downloadAndOpenFile.ts @@ -1,7 +1,7 @@ +import prettyBytes from 'pretty-bytes' import { openWorldZip } from './browserfs' import { getResourcePackName, installTexturePack, resourcePackState, updateTexturePackInstalledState } from './texturePack' import { setLoadingScreenStatus } from './utils' -import prettyBytes from 'pretty-bytes' const getConstantFilesize = (bytes: number) => { return prettyBytes(bytes, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) @@ -15,14 +15,14 @@ export default async () => { if (texturepack) mapUrl = texturepack if (!mapUrl) return false - if (!texturepack) { - const menu = document.getElementById('play-screen') - menu.style = 'display: none;' - } else { + if (texturepack) { await updateTexturePackInstalledState() if (resourcePackState.resourcePackInstalled) { - if (!confirm(`You are going to install a new texturepack which would override a current one: ${getResourcePackName()} Continue?`)) return + if (!confirm(`You are going to install a new texturepack which would override a current one: ${await getResourcePackName()} Continue?`)) return } + } else { + const menu = document.getElementById('play-screen') + menu.style = 'display: none;' } const name = mapUrl.slice(mapUrl.lastIndexOf('/') + 1).slice(-25) const downloadThing = texturepack ? 'texturepack' : 'world' @@ -42,6 +42,7 @@ export default async () => { async start(controller) { const reader = response.body.getReader() + // eslint-disable-next-line no-constant-condition while (true) { const { done, value } = await reader.read() diff --git a/src/dragndrop.ts b/src/dragndrop.ts index bcb8d571..5a114553 100644 --- a/src/dragndrop.ts +++ b/src/dragndrop.ts @@ -1,5 +1,5 @@ -import * as nbt from 'prismarine-nbt' import { promisify } from 'util' +import * as nbt from 'prismarine-nbt' import { showNotification } from './menus/notification' import { openWorldDirectory, openWorldZip } from './browserfs' import { isGameActive } from './globalState' @@ -8,7 +8,7 @@ const parseNbt = promisify(nbt.parse) window.nbt = nbt; // todo display drop zone -["drag", "dragstart", "dragend", "dragover", "dragenter", "dragleave", "drop"].forEach(event => { +for (const event of ["drag", "dragstart", "dragend", "dragover", "dragenter", "dragleave", "drop"]) { window.addEventListener(event, (e: any) => { if (e.dataTransfer && !e.dataTransfer.types.includes("Files")) { // e.dataTransfer.effectAllowed = "none" @@ -16,7 +16,7 @@ window.nbt = nbt; } e.preventDefault() }) -}) +} window.addEventListener("drop", async e => { if (!e.dataTransfer?.files.length) return const { items } = e.dataTransfer @@ -32,7 +32,7 @@ window.addEventListener("drop", async e => { alert('Exit current world first, before loading a new one.') return } - await openWorldDirectory(filehandle as FileSystemDirectoryHandle) + await openWorldDirectory(filehandle ) } } else { await handleDroppedFile(item.getAsFile()) diff --git a/src/globalState.ts b/src/globalState.ts index 50cbde65..0257ca23 100644 --- a/src/globalState.ts +++ b/src/globalState.ts @@ -45,7 +45,7 @@ const showModalInner = (modal: Modal) => { export const showModal = (elem: (HTMLElement & Record) | { reactType: string }) => { const resolved = elem instanceof HTMLElement ? { elem: ref(elem) } : elem - const curModal = activeModalStack.slice(-1)[0] + const curModal = activeModalStack.at(-1) if (elem === curModal?.elem || !showModalInner(resolved)) return if (curModal) defaultModalActions.hide(curModal) activeModalStack.push(resolved) @@ -55,7 +55,7 @@ export const showModal = (elem: (HTMLElement & Record) | { reactTyp * * @returns true if previous modal was restored */ -export const hideModal = (modal = activeModalStack.slice(-1)[0], data: any = undefined, options: { force?: boolean; restorePrevious?: boolean } = {}) => { +export const hideModal = (modal = activeModalStack.at(-1), data: any = undefined, options: { force?: boolean; restorePrevious?: boolean } = {}) => { const { force = false, restorePrevious = true } = options if (!modal) return let cancel = modal.elem?.hide?.(data) @@ -66,7 +66,7 @@ export const hideModal = (modal = activeModalStack.slice(-1)[0], data: any = und if (!cancel || cancel === customDisplayManageKeyword) { if (cancel !== customDisplayManageKeyword) defaultModalActions.hide(modal) activeModalStack.pop() - const newModal = activeModalStack.slice(-1)[0] + const newModal = activeModalStack.at(-1) if (newModal && restorePrevious) { // would be great to ignore cancel I guess? showModalInner(newModal) @@ -79,10 +79,10 @@ export const hideCurrentModal = (_data = undefined, restoredActions = undefined) if (hideModal(undefined, undefined)) { restoredActions?.() if (activeModalStack.length === 0) { - if (!isGameActive(false)) { - showModal(document.getElementById('title-screen')) - } else { + if (isGameActive(false)) { pointerLock.requestPointerLock() + } else { + showModal(document.getElementById('title-screen')) } } } @@ -149,8 +149,8 @@ window.inspectPlayer = () => require('fs').promises.readFile('/world/playerdata/ window.addEventListener('beforeunload', (event) => { // todo-low maybe exclude chat? if (!isGameActive(true) && activeModalStack.at(-1)?.elem.id !== 'chat') return - if (sessionStorage.lastReload && options.preventDevReloadWhilePlaying === false) return - if (options.closeConfirmation === false) return + if (sessionStorage.lastReload && !options.preventDevReloadWhilePlaying) return + if (!options.closeConfirmation) return // For major browsers doning only this is enough event.preventDefault() diff --git a/src/globals.d.ts b/src/globals.d.ts index dadeafa7..d1d5543a 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -30,10 +30,10 @@ type StringKeys = Extract interface ObjectConstructor { - keys(obj: T): StringKeys[] - entries(obj: T): [StringKeys, T[keyof T]][] + keys(obj: T): Array> + entries(obj: T): Array<[StringKeys, T[keyof T]]> // todo review https://stackoverflow.com/questions/57390305/trying-to-get-fromentries-type-right - fromEntries(obj: T): Record + fromEntries>(obj: T): Record assign, K extends Record>(target: T, source: K): asserts target is T & K } diff --git a/src/index.ts b/src/index.ts index 2dcc76a5..59d8043d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable import/order */ import './importsWorkaround' import './styles.css' import './globals' @@ -25,9 +26,9 @@ import './menus/advanced_options_screen' import { notification } from './menus/notification' import './menus/title_screen' -import './optionsStorage' +import { options, watchValue } from './optionsStorage' import './reactUi.jsx' -import './controls' +import { contro } from './controls' import './dragndrop' import './browserfs' import './eruda' @@ -75,25 +76,24 @@ import { import { startLocalServer, unsupportedLocalServerFeatures } from './createLocalServer' import serverOptions from './defaultLocalServerOptions' import updateTime from './updateTime' -import { options, watchValue } from './optionsStorage' + import { subscribeKey } from 'valtio/utils' import _ from 'lodash' -import { contro } from './controls' + import { genTexturePackTextures, watchTexturepackInViewer } from './texturePack' import { connectToPeer } from './localServerMultiplayer' import CustomChannelClient from './customClient' import debug from 'debug' window.debug = debug -//@ts-ignore window.THREE = THREE if ('serviceWorker' in navigator && !isCypress() && process.env.NODE_ENV !== 'development') { window.addEventListener('load', () => { navigator.serviceWorker.register('./service-worker.js').then(registration => { - console.log('SW registered: ', registration) + console.log('SW registered:', registration) }).catch(registrationError => { - console.log('SW registration failed: ', registrationError) + console.log('SW registration failed:', registrationError) }) }) } @@ -101,10 +101,8 @@ if ('serviceWorker' in navigator && !isCypress() && process.env.NODE_ENV !== 'de // ACTUAL CODE // todo stats-gl -let stats -let stats2 -stats = new Stats() -stats2 = new Stats() +const stats = new Stats() +const stats2 = new Stats() stats2.showPanel(2) document.body.appendChild(stats.dom) @@ -121,19 +119,6 @@ if (localStorage.hideStats || isCypress()) { stats2.dom.style.display = 'none' } -// const debugPitch = document.createElement('span') -// debugPitch.style.cssText = ` -// position: absolute; -// top: 0; -// right: 0; -// z-index: 100; -// color:white; -// ` -// document.body.appendChild(debugPitch) - -const maxPitch = 0.5 * Math.PI -const minPitch = -0.5 * Math.PI - // Create three.js context, add to page const renderer = new THREE.WebGLRenderer() renderer.setPixelRatio(window.devicePixelRatio || 1) // todo this value is too high on ios, need to check, probably we should use avg, also need to make it configurable @@ -163,7 +148,7 @@ const renderFrame = (time: DOMHighResTimeStamp) => { delta += time - lastTime lastTime = time if (delta > renderInterval) { - delta = delta % renderInterval + delta %= renderInterval // continue rendering } else { return @@ -207,7 +192,6 @@ function onCameraMove(e) { lastMouseMove = now let { mouseSensX, mouseSensY } = options if (mouseSensY === true) mouseSensY = mouseSensX - // debugPitch.innerText = +debugPitch.innerText + e.movementX mouseMovePostHandle({ x: e.movementX * mouseSensX * 0.0001, y: e.movementY * mouseSensY * 0.0001 @@ -234,7 +218,7 @@ async function main() { connect({ server: '', port: '', proxy: '', singleplayer: true, username: options.localUsername, password: '', serverOverrides }) } document.querySelector('#title-screen').addEventListener('singleplayer', (e) => { - //@ts-ignore + //@ts-expect-error connectSingleplayer(e.detail) }) const qs = new URLSearchParams(window.location.search) @@ -247,9 +231,7 @@ async function main() { } let listeners = [] -let disposables = [] let timeouts = [] -let intervals = [] // only for dom listeners (no removeAllListeners) // todo refactor them out of connect fn instead const registerListener: import('./utilsTs').RegisterListener = (target, event, callback) => { @@ -257,16 +239,14 @@ const registerListener: import('./utilsTs').RegisterListener = (target, event, c listeners.push({ target, event, callback }) } const removeAllListeners = () => { - listeners.forEach(({ target, event, callback }) => { + for (const { target, event, callback } of listeners) { target.removeEventListener(event, callback) - }) - listeners = [] - for (const disposable of disposables) { - disposable() } - disposables = [] + listeners = [] } +// todo +// eslint-disable-next-line complexity async function connect(connectOptions: { server: any; port?: string; singleplayer?: any; username: any; password: any; proxy: any; botVersion?: any; serverOverrides?; peerId?: string }) { @@ -278,15 +258,8 @@ async function connect(connectOptions: { const p2pMultiplayer = !!connectOptions.peerId miscUiState.singleplayer = singeplayer miscUiState.flyingSquid = singeplayer || p2pMultiplayer - const oldSetInterval = window.setInterval - // @ts-ignore - window.setInterval = (callback, ms) => { - const id = oldSetInterval.call(window, callback, ms) - timeouts.push(id) - return id - } const oldSetTimeout = window.setTimeout - //@ts-ignore + //@ts-expect-error window.setTimeout = (callback, ms) => { const id = oldSetTimeout.call(window, callback, ms) timeouts.push(id) @@ -295,24 +268,24 @@ async function connect(connectOptions: { const { renderDistance, maxMultiplayerRenderDistance } = options const hostprompt = connectOptions.server const proxyprompt = connectOptions.proxy - const username = connectOptions.username - const password = connectOptions.password + const { username } = connectOptions + const { password } = connectOptions - let host, port, proxy, proxyport - if (!hostprompt.includes(':')) { - host = hostprompt - port = 25565 - } else { + let host; let port; let proxy; let proxyport + if (hostprompt.includes(':')) { [host, port] = hostprompt.split(':') port = parseInt(port, 10) + } else { + host = hostprompt + port = 25_565 } - if (!proxyprompt.includes(':')) { - proxy = proxyprompt - proxyport = undefined - } else { + if (proxyprompt.includes(':')) { [proxy, proxyport] = proxyprompt.split(':') proxyport = parseInt(proxyport, 10) + } else { + proxy = proxyprompt + proxyport = undefined } console.log(`connecting to ${host} ${port} with ${username}`) @@ -338,10 +311,6 @@ async function connect(connectOptions: { clearTimeout(timeout) } timeouts = [] - for (const interval of intervals) { - clearInterval(interval) - } - intervals = [] } const handleError = (err) => { console.log('Encountered error!', err) @@ -389,7 +358,7 @@ async function connect(connectOptions: { // console.error(err) // throw new Error(`Proxy server ${proxy}:${proxyport} is not available`) // } - //@ts-ignore + //@ts-expect-error net.setProxy({ hostname: proxy, port: proxyport }) } @@ -444,7 +413,7 @@ async function connect(connectOptions: { bot = mineflayer.createBot({ host, port, - version: !connectOptions.botVersion ? false : connectOptions.botVersion, + version: connectOptions.botVersion || false, ...p2pMultiplayer ? { stream: await connectToPeer(connectOptions.peerId), } : {}, @@ -483,7 +452,7 @@ async function connect(connectOptions: { } else { bot._client.socket.on('connect', () => { console.log('TCP connection established') - //@ts-ignore + //@ts-expect-error bot._client.socket._ws.addEventListener('close', () => { console.log('TCP connection closed') setTimeout(() => { @@ -499,7 +468,7 @@ async function connect(connectOptions: { } if (!bot) return - let p2pConnectTimeout = p2pMultiplayer ? setTimeout(() => { throw new Error('Spawn timeout. There might be error on other side, check console.') }, 20_000) : undefined + const p2pConnectTimeout = p2pMultiplayer ? setTimeout(() => { throw new Error('Spawn timeout. There might be error on other side, check console.') }, 20_000) : undefined hud.preload(bot) // bot.on('inject_allowed', () => { @@ -539,7 +508,7 @@ async function connect(connectOptions: { console.log('bot spawned - starting viewer') - const version = bot.version + const { version } = bot const center = bot.entity.position @@ -611,6 +580,8 @@ async function connect(connectOptions: { setLoadingScreenStatus('Setting callbacks') + const maxPitch = 0.5 * Math.PI + const minPitch = -0.5 * Math.PI mouseMovePostHandle = ({ x, y }) => { bot.entity.pitch -= y bot.entity.pitch = Math.max(minPitch, Math.min(maxPitch, bot.entity.pitch)) @@ -743,7 +714,7 @@ async function connect(connectOptions: { hud.style.display = 'block' blockInteraction.init() - setTimeout(function () { + setTimeout(() => { errorAbortController.abort() if (loadingScreen.hasError) return // remove loading screen, wait a second to make sure a frame has properly rendered @@ -769,15 +740,13 @@ window.addEventListener('keydown', (e) => { pointerLock.justHitEscape = true } }) - } else { - if (pointerLock.hasPointerLock) { - document.exitPointerLock() - if (options.autoExitFullscreen) { - document.exitFullscreen() - } - } else { - document.dispatchEvent(new Event('pointerlockchange')) + } else if (pointerLock.hasPointerLock) { + document.exitPointerLock() + if (options.autoExitFullscreen) { + document.exitFullscreen() } + } else { + document.dispatchEvent(new Event('pointerlockchange')) } }) @@ -793,9 +762,9 @@ window.addEventListener('keydown', (e) => { addPanoramaCubeMap() showModal(document.getElementById('title-screen')) -main() +void main() downloadAndOpenFile().then((downloadAction) => { - if (downloadAction !== false) return + if (downloadAction) return window.addEventListener('hud-ready', (e) => { // try to connect to peer diff --git a/src/inventory.ts b/src/inventory.ts index 2efce7fc..e4dd2d85 100644 --- a/src/inventory.ts +++ b/src/inventory.ts @@ -1,16 +1,16 @@ import { subscribe } from 'valtio' -import { activeModalStack, hideCurrentModal, miscUiState } from './globalState' import { showInventory } from 'minecraft-inventory-gui/web/ext.mjs' import InventoryGui from 'minecraft-assets/minecraft-assets/data/1.17.1/gui/container/inventory.png' import Dirt from 'minecraft-assets/minecraft-assets/data/1.17.1/blocks/dirt.png' import { subscribeKey } from 'valtio/utils' import MinecraftData from 'minecraft-data' -import invspriteJson from './invsprite.json' import { getVersion } from 'prismarine-viewer/viewer/lib/version' +import invspriteJson from './invsprite.json' +import { activeModalStack, hideCurrentModal, miscUiState } from './globalState' const loadedImages = new Map() export type BlockStates = Record + }>> }> let blockStates: BlockStates @@ -37,7 +37,7 @@ subscribeKey(miscUiState, 'gameLoaded', async () => { // on game load version = getVersion(bot.version) - blockStates = await fetch(`blocksStates/${version}.json`).then(res => res.json()) + blockStates = await fetch(`blocksStates/${version}.json`).then(async res => res.json()) getImage({ path: 'blocks', } as any) getImage({ path: 'invsprite', } as any) mcData = MinecraftData(version) @@ -53,7 +53,7 @@ const findBlockStateTexturesAtlas = (name) => { const getBlockData = (name) => { const blocksImg = loadedImages.get('blocks') - if (!blocksImg || !blocksImg.width) return + if (!blocksImg?.width) return const data = findBlockStateTexturesAtlas(name) if (!data) return @@ -79,7 +79,7 @@ const getBlockData = (name) => { const getItemSlice = (name) => { const invspriteImg = loadedImages.get('invsprite') - if (!invspriteImg || !invspriteImg.width) return + if (!invspriteImg?.width) return const { x, y } = invspriteJson[name] ?? /* unknown item */ { x: 0, y: 0 } const sprite = [x, y, 32, 32] @@ -131,7 +131,7 @@ const upInventory = () => { } subscribe(activeModalStack, () => { - const inventoryOpened = activeModalStack.slice(-1)[0]?.reactType === 'inventory' + const inventoryOpened = activeModalStack.at(-1)?.reactType === 'inventory' if (inventoryOpened) { const inv = showInventory(undefined, getImage, {}, bot) inv.canvas.style.zIndex = 10 diff --git a/src/loadSave.ts b/src/loadSave.ts index 4edcafd4..22aff77d 100644 --- a/src/loadSave.ts +++ b/src/loadSave.ts @@ -1,12 +1,12 @@ import fs from 'fs' +import { promisify } from 'util' import { supportedVersions } from 'flying-squid/src/lib/version' import * as nbt from 'prismarine-nbt' -import { promisify } from 'util' -import { options } from './optionsStorage' import { proxy } from 'valtio' +import { gzip } from 'node-gzip' +import { options } from './optionsStorage' import { nameToMcOfflineUUID } from './utils' import { forceCachedDataPaths } from './browserfs' -import { gzip } from 'node-gzip' const parseNbt = promisify(nbt.parse) @@ -20,11 +20,14 @@ export const fsState = proxy({ const PROPOSE_BACKUP = true +// eslint-disable-next-line complexity export const loadSave = async (root = '/world') => { const disablePrompts = options.disableLoadPrompts // todo do it in singleplayer as well + // eslint-disable-next-line guard-for-in for (const key in forceCachedDataPaths) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete forceCachedDataPaths[key] } @@ -35,10 +38,10 @@ export const loadSave = async (root = '/world') => { levelDatContent = await fs.promises.readFile(`${root}/level.dat`) } catch (err) { if (err.code === 'ENOENT') { - if (!fsState.isReadonly) { - warnings.push('level.dat not found, world in current folder will be created') - } else { + if (fsState.isReadonly) { throw new Error('level.dat not found, ensure you are loading world folder') + } else { + warnings.push('level.dat not found, world in current folder will be created') } } else { throw err @@ -54,7 +57,7 @@ export const loadSave = async (root = '/world') => { const qs = new URLSearchParams(window.location.search) version = levelDat.Version?.Name ?? qs.get('mapVersion') if (!version) { - const newVersion = disablePrompts ? '1.8.8' : prompt(`In 1.8 and before world save doesn\'t contain version info, please enter version you want to use to load the world.\nSupported versions ${supportedVersions.join(', ')}`, '1.8.8') + const newVersion = disablePrompts ? '1.8.8' : prompt(`In 1.8 and before world save doesn't contain version info, please enter version you want to use to load the world.\nSupported versions ${supportedVersions.join(', ')}`, '1.8.8') if (!newVersion) return version = newVersion } @@ -131,9 +134,9 @@ export const loadSave = async (root = '/world') => { name: 'superflat' } } : {}, - ...root !== '/world' ? { + ...root === '/world' ? {} : { 'worldFolder': root - } : {} + } }, })) } diff --git a/src/localServerMultiplayer.ts b/src/localServerMultiplayer.ts index a6382284..71efd25b 100644 --- a/src/localServerMultiplayer.ts +++ b/src/localServerMultiplayer.ts @@ -84,7 +84,7 @@ export const openToWanAndCopyJoinLink = async (writeText: (text) => void, doCopy console.error(error) writeText(error.message) }) - return await new Promise(resolve => { + return new Promise(resolve => { peer.on('open', async () => { await copyJoinLink() resolve('Copied join link to clipboard') @@ -120,7 +120,7 @@ export const connectToPeer = async (peerId: string) => { connection.once('error', (error) => { console.log(error.type, error.name) console.log(error) - return reject(error.message) + reject(error.message); }) connection.once('open', resolve) })) diff --git a/src/optionsStorage.ts b/src/optionsStorage.ts index 51aeb35d..64850314 100644 --- a/src/optionsStorage.ts +++ b/src/optionsStorage.ts @@ -62,11 +62,11 @@ export const watchValue: WatchValue = (proxy, callback) => { return Reflect.get(target, p, receiver) }, })) - watchedProps.forEach(prop => { + for (const prop of watchedProps) { subscribeKey(proxy, prop, () => { callback(proxy) }) - }) + } } watchValue(options, o => { diff --git a/src/panorama.js b/src/panorama.js index 1c67df82..21d01359 100644 --- a/src/panorama.js +++ b/src/panorama.js @@ -37,7 +37,7 @@ const possiblyLoadPanoramaFromResourcePack = async (file) => { else return join('extra-textures/background', file) } -const updateResourecePackSupportPanorama = async () => { +const updateResourcePackSupportPanorama = async () => { try { await fs.promises.readFile(fromTexturePackPath(join(panoramaResourcePackPath, panoramaFiles[0])), 'base64') panoramaUsesResourePack = true @@ -48,7 +48,7 @@ const updateResourecePackSupportPanorama = async () => { subscribeKey(resourcePackState, 'resourcePackInstalled', async () => { const oldState = panoramaUsesResourePack - const newState = resourcePackState.resourcePackInstalled && (await updateResourecePackSupportPanorama(), panoramaUsesResourePack) + const newState = resourcePackState.resourcePackInstalled && (await updateResourcePackSupportPanorama(), panoramaUsesResourePack) if (newState === oldState) return removePanorama() addPanoramaCubeMap() @@ -56,6 +56,7 @@ subscribeKey(resourcePackState, 'resourcePackInstalled', async () => { // Menu panorama background export async function addPanoramaCubeMap () { + if (panoramaCubeMap) return // remove all existing object in the viewer.scene // viewer.scene.children = [] @@ -68,7 +69,7 @@ export async function addPanoramaCubeMap () { const loader = new THREE.TextureLoader() let panorMaterials = [] - await updateResourecePackSupportPanorama() + await updateResourcePackSupportPanorama() for (const file of panoramaFiles) { panorMaterials.push(new THREE.MeshBasicMaterial({ map: loader.load(await possiblyLoadPanoramaFromResourcePack(file)), diff --git a/src/reactUi.jsx b/src/reactUi.jsx index efe49792..136fcb8b 100644 --- a/src/reactUi.jsx +++ b/src/reactUi.jsx @@ -3,12 +3,12 @@ import { renderToDom } from '@zardoy/react-util' import { LeftTouchArea, RightTouchArea, useUsingTouch, useInterfaceState } from '@dimaka/interface' import { css } from '@emotion/css' -import { activeModalStack, isGameActive, miscUiState } from './globalState' // import DeathScreen from './react/DeathScreen' import { useSnapshot } from 'valtio' -import { contro } from './controls' import { QRCodeSVG } from 'qrcode.react' import { createPortal } from 'react-dom' +import { contro } from './controls' +import { activeModalStack, isGameActive, miscUiState } from './globalState' import { options, watchValue } from './optionsStorage' // todo @@ -17,7 +17,7 @@ useInterfaceState.setState({ uiCustomization: { touchButtonSize: 40, }, - updateCoord: ([coord, state]) => { + updateCoord([coord, state]) { const coordToAction = [ ['z', -1, 'KeyW'], ['z', 1, 'KeyS'], @@ -27,14 +27,14 @@ useInterfaceState.setState({ ['y', -1, 'ShiftLeft'], // todo jump ] // todo refactor - const actionAndState = state !== 0 ? coordToAction.find(([axis, value]) => axis === coord && value === state) : coordToAction.filter(([axis]) => axis === coord) + const actionAndState = state === 0 ? coordToAction.filter(([axis]) => axis === coord) : coordToAction.find(([axis, value]) => axis === coord && value === state) if (!bot) return if (state === 0) { for (const action of actionAndState) { contro.pressedKeyOrButtonChanged({code: action[2],}, false) } } else { - //@ts-ignore + //@ts-expect-error contro.pressedKeyOrButtonChanged({code: actionAndState[2],}, true) } } diff --git a/src/texturePack.ts b/src/texturePack.ts index 0f54e296..df58ceea 100644 --- a/src/texturePack.ts +++ b/src/texturePack.ts @@ -1,14 +1,14 @@ -import { setLoadingScreenStatus } from './utils' -import blocksFileNames from '../generated/blocks.json' -import JSZip from 'jszip' import { join, dirname } from 'path' import fs from 'fs' -import type { BlockStates } from './inventory' +import JSZip from 'jszip' import type { Viewer } from 'prismarine-viewer/viewer/lib/viewer' -import { removeFileRecursiveAsync } from './browserfs' import { subscribeKey } from 'valtio/utils' -import { showNotification } from './menus/notification' import { proxy, ref } from 'valtio' +import blocksFileNames from '../generated/blocks.json' +import { showNotification } from './menus/notification' +import type { BlockStates } from './inventory' +import { removeFileRecursiveAsync } from './browserfs' +import { setLoadingScreenStatus } from './utils' export const resourcePackState = proxy({ resourcePackInstalled: false, @@ -130,7 +130,7 @@ const applyTexturePackData = async (version: string, { blockSize }: TextureResol for (const v of x) { processObj(v) } - return + } else { const actual = Object.keys(x) const needed = ['u', 'v', 'su', 'sv'] @@ -161,7 +161,7 @@ const getSizeFromImage = async (filePath: string) => { const file = await fs.promises.readFile(filePath, 'base64') probeImg.src = `data:image/png;base64,${file}` await new Promise((resolve, reject) => { - probeImg.onload = resolve + probeImg.addEventListener('load', resolve) }) if (probeImg.width !== probeImg.height) throw new Error(`Probe texture ${filePath} is not square`) return probeImg.width @@ -174,14 +174,14 @@ export const genTexturePackTextures = async (version: string) => { const blocksBasePathAlt = '/userData/resourcePacks/default/assets/minecraft/textures/blocks' const blocksGenereatedPath = `/userData/resourcePacks/default/${version}.png` const genereatedPathData = `/userData/resourcePacks/default/${version}.json` - if (await existsAsync(blocksBasePath) === false) { - if (await existsAsync(blocksBasePathAlt) === false) { - return - } else { + if (!(await existsAsync(blocksBasePath))) { + if (await existsAsync(blocksBasePathAlt)) { blocksBasePath = blocksBasePathAlt + } else { + return } } - if (await existsAsync(blocksGenereatedPath) === true) { + if (await existsAsync(blocksGenereatedPath)) { applyTexturePackData(version, JSON.parse(await fs.promises.readFile(genereatedPathData, 'utf8')), await fs.promises.readFile(blocksGenereatedPath, 'utf8')) return } @@ -214,7 +214,7 @@ export const genTexturePackTextures = async (version: string) => { img.src = src await new Promise((resolve, reject) => { img.onerror = reject - img.onload = resolve + img.addEventListener('load', resolve) }) for (const [i, fileName] of textureFiles.entries()) { const x = (i % texSize) * tileSize @@ -226,10 +226,10 @@ export const genTexturePackTextures = async (version: string) => { const fileBase64 = await fs.promises.readFile(join(blocksBasePath, fileName), 'base64') const _imgCustom = new Image() await new Promise(resolve => { - _imgCustom.onload = () => { + _imgCustom.addEventListener('load', () => { imgCustom = _imgCustom resolve() - } + }) _imgCustom.onerror = () => { console.log('Skipping issued texture', fileName) resolve() diff --git a/src/updateTime.ts b/src/updateTime.ts index 3d871ff5..6ba296ad 100644 --- a/src/updateTime.ts +++ b/src/updateTime.ts @@ -2,15 +2,16 @@ export default (bot: import('mineflayer').Bot) => { bot.on('time', () => { // 0 morning const dayTotal = 24_000 - const evening = 12542 / dayTotal - const night = 17843 / dayTotal - const morningStart = 22300 / dayTotal - const morningEnd = 23961 / dayTotal + const evening = 12_542 / dayTotal + const night = 17_843 / dayTotal + const morningStart = 22_300 / dayTotal + const morningEnd = 23_961 / dayTotal const timeProgress = bot.time.time / dayTotal // todo check actual colors const dayColorRainy = { r: 111 / 255, g: 156 / 255, b: 236 / 255 } // todo yes, we should make animations (and rain) + // eslint-disable-next-line unicorn/numeric-separators-style const dayColor = bot.isRaining ? dayColorRainy : { r: 0.6784313725490196, g: 0.8470588235294118, b: 0.9019607843137255 } // lightblue // let newColor = dayColor let int = 1 diff --git a/src/utils.ts b/src/utils.ts index 03e6df79..40e05463 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,7 @@ -import { activeModalStack, hideModal, miscUiState, showModal } from './globalState' -import { notification } from './menus/notification' import * as crypto from 'crypto' import UUID from 'uuid-1345' +import { activeModalStack, hideModal, miscUiState, showModal } from './globalState' +import { notification } from './menus/notification' import { options } from './optionsStorage' import { saveWorld } from './builtinCommands' import { openWorldZip } from './browserfs' @@ -12,7 +12,7 @@ export const goFullscreen = async (doToggle = false) => { // todo display a message or repeat? await document.documentElement.requestFullscreen().catch(() => { }) // request full keyboard access - //@ts-ignore + //@ts-expect-error navigator.keyboard?.lock?.(['Escape', 'KeyW']) } else if (doToggle) { await document.exitFullscreen().catch(() => { }) @@ -43,7 +43,7 @@ export const pointerLock = { if (!(document.fullscreenElement && navigator['keyboard']) && this.justHitEscape) { displayBrowserProblem() } else { - //@ts-ignore + //@ts-expect-error const promise: any = document.documentElement.requestPointerLock({ unadjustedMovement: options.mouseRawInput }) @@ -68,7 +68,7 @@ window.getScreenRefreshRate = getScreenRefreshRate /** * Allows to obtain the estimated Hz of the primary monitor in the system. */ -export function getScreenRefreshRate(): Promise { +export async function getScreenRefreshRate(): Promise { let requestId = null let callbackTriggered = false let resolve @@ -79,8 +79,8 @@ export function getScreenRefreshRate(): Promise { DOMHighResTimeStampCollection.unshift(DOMHighResTimeStamp) if (DOMHighResTimeStampCollection.length > 10) { - let t0 = DOMHighResTimeStampCollection.pop() - let fps = Math.floor(1000 * 10 / (DOMHighResTimeStamp - t0)) + const t0 = DOMHighResTimeStampCollection.pop() + const fps = Math.floor(1000 * 10 / (DOMHighResTimeStamp - t0)) if (!callbackTriggered) { resolve(fps/* , DOMHighResTimeStampCollection */) @@ -177,9 +177,9 @@ export const loadScript = async function (scriptSrc: string) { scriptElement.src = scriptSrc scriptElement.async = true - scriptElement.onload = () => { + scriptElement.addEventListener('load', () => { resolve(scriptElement) - } + }) scriptElement.onerror = (error) => { reject(error) @@ -191,7 +191,7 @@ export const loadScript = async function (scriptSrc: string) { // doesn't support snapshots export const toMajorVersion = (version) => { - const [a, b] = (version + '').split('.') + const [a, b] = (String(version)).split('.') return `${a}.${b}` } @@ -239,7 +239,7 @@ export const openFilePicker = (specificCase?: 'resourcepack') => { picker.click() } -export const resolveTimeout = (promise, timeout = 10000) => { +export const resolveTimeout = async (promise, timeout = 10_000) => { return new Promise((resolve, reject) => { promise.then(resolve, reject) setTimeout(() => { diff --git a/src/utilsTs.ts b/src/utilsTs.ts index 75cd623a..5c5f0999 100644 --- a/src/utilsTs.ts +++ b/src/utilsTs.ts @@ -3,29 +3,25 @@ type Options = boolean | Readonly | undefined function registerListener( element: Readonly | null | undefined, eventType: KD, - // eslint-disable-next-line functional/prefer-immutable-types listener: (this: Document, evt: DocumentEventMap[KD]) => void, options?: Options, ): void function registerListener( element: Readonly | null | undefined, eventType: KH, - // eslint-disable-next-line functional/prefer-immutable-types listener: (this: HTMLElement, evt: HTMLElementEventMap[KH]) => void, options?: Options, ): void function registerListener( element: Readonly | null | undefined, eventType: KW, - // eslint-disable-next-line functional/prefer-immutable-types listener: (this: Window, evt: WindowEventMap[KW]) => void, options?: Options, ): void -//@ts-ignore +//@ts-expect-error function registerListener( element: Readonly | null | undefined, eventType: string, - // eslint-disable-next-line functional/prefer-immutable-types listener: (evt: Event) => void, options?: Options, ): void