From 1c27b0acf60afb3245ccb709de0f51e35335ca2d Mon Sep 17 00:00:00 2001 From: Nuria Date: Wed, 8 Feb 2023 12:58:31 +0100 Subject: [PATCH 1/4] style: add eslint-config-codely and autofix issues --- .eslintrc.js | 26 +- package-lock.json | 505 +++++++++++++++--- package.json | 12 +- .../network-request/NetworkRequestCommand.ts | 16 +- .../NetworkRequestCommandHandler.ts | 40 +- src/commands-setup/Command.ts | 4 +- src/commands-setup/CommandHandler.ts | 2 +- src/commands-setup/CommandsMapping.ts | 8 +- src/commands-setup/executeCommand.ts | 8 +- src/commands-setup/handleCommand.ts | 65 +-- src/figma-entrypoint.ts | 69 ++- src/scene-commands/cancel/CancelCommand.ts | 2 +- .../cancel/CancelCommandHandler.ts | 12 +- .../create-shapes/CreateShapesCommand.ts | 16 +- .../CreateShapesCommandHandler.ts | 139 +++-- .../PaintCurrentUserAvatarCommand.ts | 2 +- .../PaintCurrentUserAvatarCommandHandler.ts | 167 +++--- src/ui/register-ui-command-handlers.ts | 14 +- src/ui/register-ui-event-listeners.ts | 28 +- .../CancelCommandHandler.test.ts | 30 +- tsconfig.json | 2 +- 21 files changed, 723 insertions(+), 444 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 83ae96e..dc4b73f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,19 +1,11 @@ module.exports = { - parser: "@typescript-eslint/parser", - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended", - ], - plugins: ["simple-import-sort", "import"], - parserOptions: { - ecmaVersion: 12, - sourceType: "module", - }, - rules: { - "simple-import-sort/imports": "error", - "simple-import-sort/exports": "error", - "import/first": "error", - "import/newline-after-import": "error", - "import/no-duplicates": "error", - }, + extends: ["eslint-config-codely/typescript"], + overrides: [ + { + files: ["*.ts", "*.tsx"], + parserOptions: { + project: ["./tsconfig.json"], + }, + }, + ], }; diff --git a/package-lock.json b/package-lock.json index de4a28b..1e18c08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,20 +16,14 @@ "@swc/core": "^1.2.218", "@swc/jest": "^0.2.22", "@types/jest": "^28.1.6", - "@typescript-eslint/eslint-plugin": "^5.30.7", - "@typescript-eslint/parser": "^5.30.7", "css-loader": "^6.7.1", - "eslint": "^8.20.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^26.6.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint": "^8.33.0", + "eslint-config-codely": "^2.1.3", + "eslint-plugin-jest": "^27.2.1", "html-inline-script-webpack-plugin": "^3.0.1", "html-webpack-plugin": "^5.5.0", "jest": "^28.1.3", "jest-mock-extended": "^2.0.7", - "prettier": "^2.7.1", "style-loader": "^3.3.1", "ts-loader": "^9.3.1", "typescript": "^4.7.4", @@ -110,6 +104,42 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/eslint-parser": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", @@ -627,15 +657,15 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.4.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -644,6 +674,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@figma/plugin-typings": { @@ -653,19 +686,32 @@ "dev": true }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -1358,6 +1404,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2212,9 +2267,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3171,13 +3226,15 @@ } }, "node_modules/eslint": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz", - "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", + "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -3187,18 +3244,21 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -3209,8 +3269,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -3222,6 +3281,33 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-codely": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/eslint-config-codely/-/eslint-config-codely-2.1.3.tgz", + "integrity": "sha512-KDNyPudTM2ai1lWbAWKcI2PT2T+v7MeGPi2xnQv1ZuCU9YfGFLLt4NWStIt3ayeWMWPo6e8RYQQP/I/faKLdcA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@types/node": "^16.11.12", + "@typescript-eslint/eslint-plugin": "^5.6.0", + "@typescript-eslint/parser": "^5.6.0", + "eslint": "^8.4.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint-plugin-unused-imports": "^2.0.0", + "prettier": "^2.5.1", + "typescript": "^4.5.2" + } + }, + "node_modules/eslint-config-codely/node_modules/@types/node": { + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", + "dev": true + }, "node_modules/eslint-config-prettier": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", @@ -3330,19 +3416,19 @@ "dev": true }, "node_modules/eslint-plugin-jest": { - "version": "26.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.6.0.tgz", - "integrity": "sha512-f8n46/97ZFdU4KqeQYqO8AEVGIhHWvkpgNBWHH3jrM28/y8llnbf3IjfIKv6p2pZIMinK1PCqbbROxs9Eud02Q==", + "version": "27.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", + "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -3383,6 +3469,36 @@ "eslint": ">=5.0.0" } }, + "node_modules/eslint-plugin-unused-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", + "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", + "dev": true, + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -3454,18 +3570,76 @@ "node": ">=4.0" } }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "dependencies": { - "acorn": "^8.7.1", + "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -3904,9 +4078,9 @@ "dev": true }, "node_modules/globals": { - "version": "13.16.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz", - "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3944,6 +4118,12 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4375,6 +4555,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -5517,6 +5706,16 @@ "@types/yargs-parser": "*" } }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7321,12 +7520,6 @@ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", "dev": true }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", @@ -7682,6 +7875,31 @@ } } }, + "@babel/eslint-parser": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", + "dev": true, + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@babel/generator": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", @@ -8075,15 +8293,15 @@ "dev": true }, "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.4.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -8098,16 +8316,22 @@ "dev": true }, "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -8693,6 +8917,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -9302,9 +9535,9 @@ "dev": true }, "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "acorn-import-assertions": { @@ -10014,13 +10247,15 @@ "dev": true }, "eslint": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz", - "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz", + "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -10030,18 +10265,21 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -10052,8 +10290,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { @@ -10071,6 +10308,69 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "eslint-config-codely": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/eslint-config-codely/-/eslint-config-codely-2.1.3.tgz", + "integrity": "sha512-KDNyPudTM2ai1lWbAWKcI2PT2T+v7MeGPi2xnQv1ZuCU9YfGFLLt4NWStIt3ayeWMWPo6e8RYQQP/I/faKLdcA==", + "dev": true, + "requires": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@types/node": "^16.11.12", + "@typescript-eslint/eslint-plugin": "^5.6.0", + "@typescript-eslint/parser": "^5.6.0", + "eslint": "^8.4.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint-plugin-unused-imports": "^2.0.0", + "prettier": "^2.5.1", + "typescript": "^4.5.2" + }, + "dependencies": { + "@types/node": { + "version": "16.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz", + "integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==", + "dev": true } } }, @@ -10171,9 +10471,9 @@ } }, "eslint-plugin-jest": { - "version": "26.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.6.0.tgz", - "integrity": "sha512-f8n46/97ZFdU4KqeQYqO8AEVGIhHWvkpgNBWHH3jrM28/y8llnbf3IjfIKv6p2pZIMinK1PCqbbROxs9Eud02Q==", + "version": "27.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", + "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" @@ -10195,6 +10495,21 @@ "dev": true, "requires": {} }, + "eslint-plugin-unused-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", + "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", + "dev": true, + "requires": { + "eslint-rule-composer": "^0.3.0" + } + }, + "eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -10229,12 +10544,12 @@ "dev": true }, "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "requires": { - "acorn": "^8.7.1", + "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" } @@ -10571,9 +10886,9 @@ "dev": true }, "globals": { - "version": "13.16.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz", - "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -10599,6 +10914,12 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -10886,6 +11207,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -11826,6 +12153,12 @@ } } }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13135,12 +13468,6 @@ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", "dev": true }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "v8-to-istanbul": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", diff --git a/package.json b/package.json index 45cf40c..f301c2f 100644 --- a/package.json +++ b/package.json @@ -25,20 +25,14 @@ "@swc/core": "^1.2.218", "@swc/jest": "^0.2.22", "@types/jest": "^28.1.6", - "@typescript-eslint/eslint-plugin": "^5.30.7", - "@typescript-eslint/parser": "^5.30.7", "css-loader": "^6.7.1", - "eslint": "^8.20.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^26.6.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-simple-import-sort": "^7.0.0", + "eslint": "^8.33.0", + "eslint-config-codely": "^2.1.3", + "eslint-plugin-jest": "^27.2.1", "html-inline-script-webpack-plugin": "^3.0.1", "html-webpack-plugin": "^5.5.0", "jest": "^28.1.3", "jest-mock-extended": "^2.0.7", - "prettier": "^2.7.1", "style-loader": "^3.3.1", "ts-loader": "^9.3.1", "typescript": "^4.7.4", diff --git a/src/browser-commands/network-request/NetworkRequestCommand.ts b/src/browser-commands/network-request/NetworkRequestCommand.ts index e9fb499..b09818d 100644 --- a/src/browser-commands/network-request/NetworkRequestCommand.ts +++ b/src/browser-commands/network-request/NetworkRequestCommand.ts @@ -3,13 +3,13 @@ import { Command } from "../../commands-setup/Command"; type SupportedResponseTypes = "text" | "arraybuffer"; export class NetworkRequestCommand implements Command { - readonly type = "networkRequest"; - readonly payload: { - url: string; - responseType: SupportedResponseTypes; - }; + readonly type = "networkRequest"; + readonly payload: { + url: string; + responseType: SupportedResponseTypes; + }; - constructor(url: string, responseType: SupportedResponseTypes) { - this.payload = { url, responseType }; - } + constructor(url: string, responseType: SupportedResponseTypes) { + this.payload = { url, responseType }; + } } diff --git a/src/browser-commands/network-request/NetworkRequestCommandHandler.ts b/src/browser-commands/network-request/NetworkRequestCommandHandler.ts index c0d1ee1..7457b66 100644 --- a/src/browser-commands/network-request/NetworkRequestCommandHandler.ts +++ b/src/browser-commands/network-request/NetworkRequestCommandHandler.ts @@ -2,27 +2,25 @@ import { CommandHandler } from "../../commands-setup/CommandHandler"; import { executeCommand } from "../../commands-setup/executeCommand"; import { NetworkRequestCommand } from "./NetworkRequestCommand"; -export class NetworkRequestCommandHandler - implements CommandHandler -{ - async handle(command: NetworkRequestCommand): Promise { - const url = `https://cors-anywhere.herokuapp.com/${command.payload.url}`; - const method = "GET"; +export class NetworkRequestCommandHandler implements CommandHandler { + async handle(command: NetworkRequestCommand): Promise { + const url = `https://cors-anywhere.herokuapp.com/${command.payload.url}`; + const method = "GET"; - return new Promise((resolve) => { - const request = new XMLHttpRequest(); - request.open(method, url); - request.responseType = command.payload.responseType; - request.onload = () => { - const commandToPost = { - type: "networkRequestResponse", - payload: request.response, - }; + return new Promise((resolve) => { + const request = new XMLHttpRequest(); + request.open(method, url); + request.responseType = command.payload.responseType; + request.onload = () => { + const commandToPost = { + type: "networkRequestResponse", + payload: request.response, + }; - executeCommand(commandToPost); - resolve(); - }; - request.send(); - }); - } + executeCommand(commandToPost); + resolve(); + }; + request.send(); + }); + } } diff --git a/src/commands-setup/Command.ts b/src/commands-setup/Command.ts index 4a06c65..4f3d4a2 100644 --- a/src/commands-setup/Command.ts +++ b/src/commands-setup/Command.ts @@ -1,6 +1,6 @@ import { CommandsMapping } from "./CommandsMapping"; export interface Command { - readonly type: keyof typeof CommandsMapping; - readonly payload?: unknown; + readonly type: keyof typeof CommandsMapping; + readonly payload?: unknown; } diff --git a/src/commands-setup/CommandHandler.ts b/src/commands-setup/CommandHandler.ts index de67e29..e39e909 100644 --- a/src/commands-setup/CommandHandler.ts +++ b/src/commands-setup/CommandHandler.ts @@ -1,5 +1,5 @@ import { Command } from "./Command"; export abstract class CommandHandler { - abstract handle(command: CommandType): Promise | void; + abstract handle(command: CommandType): Promise | void; } diff --git a/src/commands-setup/CommandsMapping.ts b/src/commands-setup/CommandsMapping.ts index a63356e..efc5a97 100644 --- a/src/commands-setup/CommandsMapping.ts +++ b/src/commands-setup/CommandsMapping.ts @@ -9,8 +9,8 @@ import { CommandHandler } from "./CommandHandler"; // Define its arbitrary key and its corresponding Handler class. // Tip: Declare your Command and CommandHandler classes creating a folder inside the `src/scene-commands` or `src/browser-commands` ones depending on the things you need to get access to (see the README explanation) 😊 export const CommandsMapping: Record CommandHandler> = { - cancel: () => new CancelCommandHandler(figma), - createShapes: () => new CreateShapesCommandHandler(figma), - paintCurrentUserAvatar: () => new PaintCurrentUserAvatarCommandHandler(figma), - networkRequest: () => new NetworkRequestCommandHandler(), + cancel: () => new CancelCommandHandler(figma), + createShapes: () => new CreateShapesCommandHandler(figma), + paintCurrentUserAvatar: () => new PaintCurrentUserAvatarCommandHandler(figma), + networkRequest: () => new NetworkRequestCommandHandler(), }; diff --git a/src/commands-setup/executeCommand.ts b/src/commands-setup/executeCommand.ts index e14f8b3..dab118f 100644 --- a/src/commands-setup/executeCommand.ts +++ b/src/commands-setup/executeCommand.ts @@ -1,9 +1,9 @@ import { Command } from "./Command"; export const executeCommand = (command: Command): void => { - const isFromSceneSandboxToUiIframe = typeof window === "undefined"; + const isFromSceneSandboxToUiIframe = typeof window === "undefined"; - isFromSceneSandboxToUiIframe - ? figma.ui.postMessage(command) - : window.parent.postMessage({ pluginMessage: command }, "*"); + isFromSceneSandboxToUiIframe + ? figma.ui.postMessage(command) + : window.parent.postMessage({ pluginMessage: command }, "*"); }; diff --git a/src/commands-setup/handleCommand.ts b/src/commands-setup/handleCommand.ts index 09cf288..fa23bbb 100644 --- a/src/commands-setup/handleCommand.ts +++ b/src/commands-setup/handleCommand.ts @@ -3,39 +3,40 @@ import { Command } from "./Command"; import { CommandsMapping } from "./CommandsMapping"; export async function handleCommand(command: Command): Promise { - if (!(command.type in CommandsMapping)) { - notifyErrorToEndUser( - `Trying to execute the command \`${command.type}\` but it is not registered in the \`CommandsMapping.ts\` file. If you are the developer, go to the \`CommandsMapping.ts\` file and register it to the const with: \`${command.type}: ${command.type}CommandHandler,\`` - ); - - figma.closePlugin(); - return; - } - - const commandHandler = CommandsMapping[command.type](); - - try { - await commandHandler.handle(command); - } catch (error) { - notifyErrorToEndUser( - `"${error}" executing the command \`${command.type}\`. This command is mapped to a class in the \`CommandsMapping.ts\` file. It could be a good starting point to look for the bug 😊` - ); - } finally { - const isACommandInsideAnotherCommand = command.type === "networkRequest"; - - if (!isACommandInsideAnotherCommand) { - figma.closePlugin(); - } - } + if (!(command.type in CommandsMapping)) { + notifyErrorToEndUser( + `Trying to execute the command \`${command.type}\` but it is not registered in the \`CommandsMapping.ts\` file. If you are the developer, go to the \`CommandsMapping.ts\` file and register it to the const with: \`${command.type}: ${command.type}CommandHandler,\`` + ); + + figma.closePlugin(); + + return; + } + + const commandHandler = CommandsMapping[command.type](); + + try { + await commandHandler.handle(command); + } catch (error) { + notifyErrorToEndUser( + `"${error}" executing the command \`${command.type}\`. This command is mapped to a class in the \`CommandsMapping.ts\` file. It could be a good starting point to look for the bug 😊` + ); + } finally { + const isACommandInsideAnotherCommand = command.type === "networkRequest"; + + if (!isACommandInsideAnotherCommand) { + figma.closePlugin(); + } + } } function notifyErrorToEndUser(errorMessage: string): void { - figma.notify( - `🫣 Error in Figma plugin "${manifest.name}". See the JavaScript console for more info.`, - { error: true } - ); - - console.error( - `🫣️ Error in Figma plugin "${manifest.name}"\r\nFigma Plugin ID: "${figma.pluginId}"\r\n\r\n${errorMessage}.` - ); + figma.notify( + `🫣 Error in Figma plugin "${manifest.name}". See the JavaScript console for more info.`, + { error: true } + ); + + console.error( + `🫣️ Error in Figma plugin "${manifest.name}"\r\nFigma Plugin ID: "${figma.pluginId}"\r\n\r\n${errorMessage}.` + ); } diff --git a/src/figma-entrypoint.ts b/src/figma-entrypoint.ts index 0c948c1..670c1db 100644 --- a/src/figma-entrypoint.ts +++ b/src/figma-entrypoint.ts @@ -6,49 +6,46 @@ registerPluginMenuCommandParametersSuggestions(); registerPluginUiCommandHandlers(); function registerPluginMenuCommandHandlers() { - figma.on("run", async (event: RunEvent) => { - const hasToAccessPluginIframe = event.command === "showUi"; - if (hasToAccessPluginIframe) { - figma.showUI(__html__, { themeColors: true }); - figma.ui.resize(450, 300); - return; - } - - createInvisibleUiForBrowserApiAccess(); - - const command = { - type: event.command, - payload: event.parameters, - }; - - await handleCommand(command); - }); + figma.on("run", async (event: RunEvent) => { + const hasToAccessPluginIframe = event.command === "showUi"; + if (hasToAccessPluginIframe) { + figma.showUI(__html__, { themeColors: true }); + figma.ui.resize(450, 300); + + return; + } + + createInvisibleUiForBrowserApiAccess(); + + const command = { + type: event.command, + payload: event.parameters, + }; + + await handleCommand(command); + }); } function registerPluginMenuCommandParametersSuggestions() { - figma.parameters.on( - "input", - async ({ key, query, result }: ParameterInputEvent) => { - switch (key) { - case "typeOfShapes": - const shapes = ["Rectangle", "Ellipse"]; - const queryMatchingShapes = shapes.filter((s) => s.startsWith(query)); - - result.setSuggestions(queryMatchingShapes); - break; - default: - break; - } - } - ); + figma.parameters.on("input", async ({ key, query, result }: ParameterInputEvent) => { + switch (key) { + case "typeOfShapes": + const shapes = ["Rectangle", "Ellipse"]; + const queryMatchingShapes = shapes.filter((s) => s.startsWith(query)); + + result.setSuggestions(queryMatchingShapes); + break; + default: + break; + } + }); } function registerPluginUiCommandHandlers() { - figma.ui.onmessage = async ( - command: CommandType - ) => await handleCommand(command); + figma.ui.onmessage = async (command: CommandType) => + await handleCommand(command); } function createInvisibleUiForBrowserApiAccess() { - figma.showUI(__html__, { visible: false }); + figma.showUI(__html__, { visible: false }); } diff --git a/src/scene-commands/cancel/CancelCommand.ts b/src/scene-commands/cancel/CancelCommand.ts index 9755780..aeff9bb 100644 --- a/src/scene-commands/cancel/CancelCommand.ts +++ b/src/scene-commands/cancel/CancelCommand.ts @@ -1,5 +1,5 @@ import { Command } from "../../commands-setup/Command"; export class CancelCommand implements Command { - readonly type = "cancel"; + readonly type = "cancel"; } diff --git a/src/scene-commands/cancel/CancelCommandHandler.ts b/src/scene-commands/cancel/CancelCommandHandler.ts index a032ef3..cf9c066 100644 --- a/src/scene-commands/cancel/CancelCommandHandler.ts +++ b/src/scene-commands/cancel/CancelCommandHandler.ts @@ -2,11 +2,11 @@ import { CommandHandler } from "../../commands-setup/CommandHandler"; import { CancelCommand } from "./CancelCommand"; export class CancelCommandHandler implements CommandHandler { - constructor(private readonly figma: PluginAPI) {} + constructor(private readonly figma: PluginAPI) {} - // `command` argument needed due to polymorphism. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - handle(command: CancelCommand): void { - this.figma.notify("👋 Good bye!"); - } + // `command` argument needed due to polymorphism. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + handle(command: CancelCommand): void { + this.figma.notify("👋 Good bye!"); + } } diff --git a/src/scene-commands/create-shapes/CreateShapesCommand.ts b/src/scene-commands/create-shapes/CreateShapesCommand.ts index 496174d..4de86fe 100644 --- a/src/scene-commands/create-shapes/CreateShapesCommand.ts +++ b/src/scene-commands/create-shapes/CreateShapesCommand.ts @@ -3,13 +3,13 @@ import { Command } from "../../commands-setup/Command"; export type SupportedShapes = "Rectangle" | "Ellipse"; export class CreateShapesCommand implements Command { - readonly type = "createShapes"; - readonly payload: { - numberOfShapes: number; - typeOfShapes?: SupportedShapes; - }; + readonly type = "createShapes"; + readonly payload: { + numberOfShapes: number; + typeOfShapes?: SupportedShapes; + }; - constructor(numberOfShapes: number, typeOfShapes?: SupportedShapes) { - this.payload = { numberOfShapes, typeOfShapes }; - } + constructor(numberOfShapes: number, typeOfShapes?: SupportedShapes) { + this.payload = { numberOfShapes, typeOfShapes }; + } } diff --git a/src/scene-commands/create-shapes/CreateShapesCommandHandler.ts b/src/scene-commands/create-shapes/CreateShapesCommandHandler.ts index 87bd473..5fe11db 100644 --- a/src/scene-commands/create-shapes/CreateShapesCommandHandler.ts +++ b/src/scene-commands/create-shapes/CreateShapesCommandHandler.ts @@ -1,81 +1,66 @@ import { CommandHandler } from "../../commands-setup/CommandHandler"; import { CreateShapesCommand, SupportedShapes } from "./CreateShapesCommand"; -export class CreateShapesCommandHandler - implements CommandHandler -{ - private readonly separationBetweenShapes = 150; - - constructor(private readonly figma: PluginAPI) {} - - handle({ - payload: { numberOfShapes, typeOfShapes }, - }: CreateShapesCommand): void { - const shapes = Array.from({ length: numberOfShapes }).map( - this.toShape(typeOfShapes) - ); - - this.focusUiOn(shapes); - } - - private toShape( - typeOfShapes?: SupportedShapes - ): (_: unknown, iteration: number) => SceneNode { - return (_: unknown, iteration: number): SceneNode => { - const hasToRandomizeShapeTypes = typeOfShapes === undefined; - - const shapesCreator = hasToRandomizeShapeTypes - ? this.createRandomShape.bind(this) - : this.createShape(typeOfShapes); - - const shape = shapesCreator(); - this.styleShape(shape, iteration); - - this.figma.currentPage.appendChild(shape); - - return shape; - }; - } - - private createShape( - typeOfShapes: SupportedShapes - ): () => RectangleNode | EllipseNode { - return (): RectangleNode | EllipseNode => - typeOfShapes === "Rectangle" - ? this.figma.createRectangle() - : this.figma.createEllipse(); - } - - private createRandomShape(): RectangleNode | EllipseNode { - const isRectangleShape = this.randomBoolean(); - - if (isRectangleShape) { - return this.figma.createRectangle(); - } - - return this.figma.createEllipse(); - } - - private styleShape( - shape: RectangleNode | EllipseNode, - shapeNumber: number - ): void { - shape.x = shapeNumber * this.separationBetweenShapes; - shape.rotation = Math.random() * 100; - shape.fills = [{ type: "SOLID", color: this.randomColor() }]; - shape.name = `${shape.name} ${shapeNumber}`; - } - - private randomBoolean(): boolean { - return Math.random() < 0.5; - } - - private randomColor(): RGB { - return { r: Math.random(), g: Math.random(), b: Math.random() }; - } - - private focusUiOn(createdShapes: SceneNode[]) { - this.figma.currentPage.selection = createdShapes; - this.figma.viewport.scrollAndZoomIntoView(createdShapes); - } +export class CreateShapesCommandHandler implements CommandHandler { + private readonly separationBetweenShapes = 150; + + constructor(private readonly figma: PluginAPI) {} + + handle({ payload: { numberOfShapes, typeOfShapes } }: CreateShapesCommand): void { + const shapes = Array.from({ length: numberOfShapes }).map(this.toShape(typeOfShapes)); + + this.focusUiOn(shapes); + } + + private toShape(typeOfShapes?: SupportedShapes): (_: unknown, iteration: number) => SceneNode { + return (_: unknown, iteration: number): SceneNode => { + const hasToRandomizeShapeTypes = typeOfShapes === undefined; + + const shapesCreator = hasToRandomizeShapeTypes + ? this.createRandomShape.bind(this) + : this.createShape(typeOfShapes); + + const shape = shapesCreator(); + this.styleShape(shape, iteration); + + this.figma.currentPage.appendChild(shape); + + return shape; + }; + } + + private createShape(typeOfShapes: SupportedShapes): () => RectangleNode | EllipseNode { + return (): RectangleNode | EllipseNode => + typeOfShapes === "Rectangle" ? this.figma.createRectangle() : this.figma.createEllipse(); + } + + private createRandomShape(): RectangleNode | EllipseNode { + const isRectangleShape = this.randomBoolean(); + + if (isRectangleShape) { + return this.figma.createRectangle(); + } + + return this.figma.createEllipse(); + } + + private styleShape(shape: RectangleNode | EllipseNode, shapeNumber: number): void { + shape.x = shapeNumber * this.separationBetweenShapes; + shape.rotation = Math.random() * 100; + shape.fills = [{ type: "SOLID", color: this.randomColor() }]; + shape.name = `${shape.name} ${shapeNumber}`; + } + + private randomBoolean(): boolean { + return Math.random() < 0.5; + } + + private randomColor(): RGB { + return { r: Math.random(), g: Math.random(), b: Math.random() }; + } + + private focusUiOn(createdShapes: SceneNode[]) { + this.figma.currentPage.selection = createdShapes; + this.figma.viewport.scrollAndZoomIntoView(createdShapes); + } } diff --git a/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommand.ts b/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommand.ts index 858827b..c3cf817 100644 --- a/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommand.ts +++ b/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommand.ts @@ -1,5 +1,5 @@ import { Command } from "../../commands-setup/Command"; export class PaintCurrentUserAvatarCommand implements Command { - readonly type = "paintCurrentUserAvatar"; + readonly type = "paintCurrentUserAvatar"; } diff --git a/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts b/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts index b4cf5dc..9bc0d4a 100644 --- a/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts +++ b/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts @@ -4,96 +4,81 @@ import { executeCommand } from "../../commands-setup/executeCommand"; import { PaintCurrentUserAvatarCommand } from "./PaintCurrentUserAvatarCommand"; export class PaintCurrentUserAvatarCommandHandler - implements CommandHandler + implements CommandHandler { - private readonly avatarImageSize = 100; - - constructor(private readonly figma: PluginAPI) {} - - // `command` argument needed due to polymorphism. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - handle(command: PaintCurrentUserAvatarCommand): Promise { - const currentUserAvatarUrl = this.figma.currentUser?.photoUrl; - const currentUserName = this.figma.currentUser?.name; - - if (currentUserAvatarUrl === undefined || currentUserAvatarUrl === null) { - this.figma.notify("Sorry but you do not have an avatar to add 😅"); - - return Promise.resolve(); - } - - const responseType = "arraybuffer"; - executeCommand( - new NetworkRequestCommand(currentUserAvatarUrl, responseType) - ); - - return new Promise((resolve) => { - this.figma.ui.onmessage = async (command) => { - this.ensureToOnlyReceiveNetworkRequestResponse(command); - - await this.createAvatarBadge( - command.payload as ArrayBuffer, - currentUserName as string - ); - resolve(); - }; - }); - } - - private ensureToOnlyReceiveNetworkRequestResponse(command: { type: string }) { - if (command.type !== "networkRequestResponse") { - const errorMessage = - "Unexpected command received while performing the request for painting the user avatar."; - - throw new Error(errorMessage); - } - } - - private async createAvatarBadge( - imageBuffer: ArrayBuffer, - userName: string - ): Promise { - const avatarImage = this.createAvatarImage(imageBuffer, userName); - const userNameText = await this.createAvatarText(userName); - - const elementsToFocus = [avatarImage, userNameText]; - this.figma.currentPage.selection = elementsToFocus; - this.figma.viewport.scrollAndZoomIntoView(elementsToFocus); - } - - private createAvatarImage( - avatarImage: ArrayBuffer, - currentUserName: string - ): EllipseNode { - const imageUint8Array = new Uint8Array(avatarImage); - const figmaImage = this.figma.createImage(imageUint8Array); - const imageWrapper = this.figma.createEllipse(); - - imageWrapper.x = this.figma.viewport.center.x; - imageWrapper.y = this.figma.viewport.center.y; - imageWrapper.resize(this.avatarImageSize, this.avatarImageSize); - imageWrapper.fills = [ - { type: "IMAGE", scaleMode: "FILL", imageHash: figmaImage.hash }, - ]; - imageWrapper.name = `${currentUserName} avatar`; - - this.figma.currentPage.appendChild(imageWrapper); - - return imageWrapper; - } - - private async createAvatarText(userName: string): Promise { - const userNameText = this.figma.createText(); - userNameText.x = this.figma.viewport.center.x - userName.length / 2; - userNameText.y = - this.figma.viewport.center.y + - this.avatarImageSize + - this.avatarImageSize / 12; - - await this.figma.loadFontAsync(userNameText.fontName as FontName); - userNameText.characters = userName; - userNameText.fontSize = 14; - - return userNameText; - } + private readonly avatarImageSize = 100; + + constructor(private readonly figma: PluginAPI) {} + + // `command` argument needed due to polymorphism. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async handle(command: PaintCurrentUserAvatarCommand): Promise { + const currentUserAvatarUrl = this.figma.currentUser?.photoUrl; + const currentUserName = this.figma.currentUser?.name; + + if (currentUserAvatarUrl === undefined || currentUserAvatarUrl === null) { + this.figma.notify("Sorry but you do not have an avatar to add 😅"); + + return Promise.resolve(); + } + + const responseType = "arraybuffer"; + executeCommand(new NetworkRequestCommand(currentUserAvatarUrl, responseType)); + + return new Promise((resolve) => { + this.figma.ui.onmessage = async (command) => { + this.ensureToOnlyReceiveNetworkRequestResponse(command); + + await this.createAvatarBadge(command.payload as ArrayBuffer, currentUserName as string); + resolve(); + }; + }); + } + + private ensureToOnlyReceiveNetworkRequestResponse(command: { type: string }) { + if (command.type !== "networkRequestResponse") { + const errorMessage = + "Unexpected command received while performing the request for painting the user avatar."; + + throw new Error(errorMessage); + } + } + + private async createAvatarBadge(imageBuffer: ArrayBuffer, userName: string): Promise { + const avatarImage = this.createAvatarImage(imageBuffer, userName); + const userNameText = await this.createAvatarText(userName); + + const elementsToFocus = [avatarImage, userNameText]; + this.figma.currentPage.selection = elementsToFocus; + this.figma.viewport.scrollAndZoomIntoView(elementsToFocus); + } + + private createAvatarImage(avatarImage: ArrayBuffer, currentUserName: string): EllipseNode { + const imageUint8Array = new Uint8Array(avatarImage); + const figmaImage = this.figma.createImage(imageUint8Array); + const imageWrapper = this.figma.createEllipse(); + + imageWrapper.x = this.figma.viewport.center.x; + imageWrapper.y = this.figma.viewport.center.y; + imageWrapper.resize(this.avatarImageSize, this.avatarImageSize); + imageWrapper.fills = [{ type: "IMAGE", scaleMode: "FILL", imageHash: figmaImage.hash }]; + imageWrapper.name = `${currentUserName} avatar`; + + this.figma.currentPage.appendChild(imageWrapper); + + return imageWrapper; + } + + private async createAvatarText(userName: string): Promise { + const userNameText = this.figma.createText(); + userNameText.x = this.figma.viewport.center.x - userName.length / 2; + userNameText.y = + this.figma.viewport.center.y + this.avatarImageSize + this.avatarImageSize / 12; + + await this.figma.loadFontAsync(userNameText.fontName as FontName); + userNameText.characters = userName; + userNameText.fontSize = 14; + + return userNameText; + } } diff --git a/src/ui/register-ui-command-handlers.ts b/src/ui/register-ui-command-handlers.ts index a2cb6f0..6469346 100644 --- a/src/ui/register-ui-command-handlers.ts +++ b/src/ui/register-ui-command-handlers.ts @@ -1,12 +1,12 @@ import { handleCommand } from "../commands-setup/handleCommand"; export function registerUiCommandHandlers() { - window.onmessage = async (event: MessageEvent) => { - const command = { - type: event.data.pluginMessage.type, - payload: event.data.pluginMessage.payload, - }; + window.onmessage = async (event: MessageEvent) => { + const command = { + type: event.data.pluginMessage.type, + payload: event.data.pluginMessage.payload, + }; - await handleCommand(command); - }; + await handleCommand(command); + }; } diff --git a/src/ui/register-ui-event-listeners.ts b/src/ui/register-ui-event-listeners.ts index a19f726..f786dc2 100644 --- a/src/ui/register-ui-event-listeners.ts +++ b/src/ui/register-ui-event-listeners.ts @@ -3,20 +3,20 @@ import { CancelCommand } from "../scene-commands/cancel/CancelCommand"; import { CreateShapesCommand } from "../scene-commands/create-shapes/CreateShapesCommand"; export function registerUiEventListeners(): void { - document.addEventListener("click", function (event: MouseEvent) { - const target = event.target as HTMLElement; + document.addEventListener("click", function (event: MouseEvent) { + const target = event.target as HTMLElement; - switch (target.id) { - case "create": - const textBox = document.getElementById("count") as HTMLInputElement; - const countBase = 10; - const count = parseInt(textBox.value, countBase); + switch (target.id) { + case "create": + const textBox = document.getElementById("count") as HTMLInputElement; + const countBase = 10; + const count = parseInt(textBox.value, countBase); - executeCommand(new CreateShapesCommand(count)); - break; - case "cancel": - executeCommand(new CancelCommand()); - break; - } - }); + executeCommand(new CreateShapesCommand(count)); + break; + case "cancel": + executeCommand(new CancelCommand()); + break; + } + }); } diff --git a/tests/scene-commands/CancelCommandHandler.test.ts b/tests/scene-commands/CancelCommandHandler.test.ts index af94aa9..ba76a7c 100644 --- a/tests/scene-commands/CancelCommandHandler.test.ts +++ b/tests/scene-commands/CancelCommandHandler.test.ts @@ -4,24 +4,24 @@ import { CancelCommand } from "../../src/scene-commands/cancel/CancelCommand"; import { CancelCommandHandler } from "../../src/scene-commands/cancel/CancelCommandHandler"; describe("CancelCommandHandler", () => { - it("can be instantiated without throwing errors", () => { - const figmaPluginApiMock = mock(); + it("can be instantiated without throwing errors", () => { + const figmaPluginApiMock = mock(); - const cancelCommandHandlerInstantiator = () => { - new CancelCommandHandler(figmaPluginApiMock); - }; + const cancelCommandHandlerInstantiator = () => { + new CancelCommandHandler(figmaPluginApiMock); + }; - expect(cancelCommandHandlerInstantiator).not.toThrow(TypeError); - }); + expect(cancelCommandHandlerInstantiator).not.toThrow(TypeError); + }); - it("notifies the end used with a farewell message", () => { - const figmaPluginApiMock = mock(); - const cancelCommandHandler = new CancelCommandHandler(figmaPluginApiMock); - const randomCancelCommand = new CancelCommand(); + it("notifies the end used with a farewell message", () => { + const figmaPluginApiMock = mock(); + const cancelCommandHandler = new CancelCommandHandler(figmaPluginApiMock); + const randomCancelCommand = new CancelCommand(); - cancelCommandHandler.handle(randomCancelCommand); + cancelCommandHandler.handle(randomCancelCommand); - const farewellMessage = "👋 Good bye!"; - expect(figmaPluginApiMock.notify).toHaveBeenCalledWith(farewellMessage); - }); + const farewellMessage = "👋 Good bye!"; + expect(figmaPluginApiMock.notify).toHaveBeenCalledWith(farewellMessage); + }); }); diff --git a/tsconfig.json b/tsconfig.json index 9ef21c2..259ccd1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,6 @@ "./node_modules/@figma" ] }, - "include": ["src/**/*.ts"], + "include": ["src/**/*.ts", "tests/**/*.ts"], "exclude": ["node_modules"] } From 97dfc9c9a146d04cbb0543f3e1e12b7593c72c61 Mon Sep 17 00:00:00 2001 From: Nuria Date: Wed, 8 Feb 2023 13:36:23 +0100 Subject: [PATCH 2/4] style: fix more issues --- .eslintrc.js | 3 +++ .../NetworkRequestCommandHandler.ts | 2 +- src/commands-setup/handleCommand.ts | 8 ++++++-- src/figma-entrypoint.ts | 14 ++++++++------ src/scene-commands/cancel/CancelCommandHandler.ts | 2 +- .../PaintCurrentUserAvatarCommandHandler.ts | 12 +++++++----- src/ui/register-ui-command-handlers.ts | 9 +++++++-- src/ui/register-ui-event-listeners.ts | 6 ++++-- tests/.eslintrc | 6 +++++- 9 files changed, 42 insertions(+), 20 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index dc4b73f..e9f3425 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,6 +6,9 @@ module.exports = { parserOptions: { project: ["./tsconfig.json"], }, + rules: { + "@typescript-eslint/no-floating-promises": "warn", + }, }, ], }; diff --git a/src/browser-commands/network-request/NetworkRequestCommandHandler.ts b/src/browser-commands/network-request/NetworkRequestCommandHandler.ts index 7457b66..9833e7e 100644 --- a/src/browser-commands/network-request/NetworkRequestCommandHandler.ts +++ b/src/browser-commands/network-request/NetworkRequestCommandHandler.ts @@ -14,7 +14,7 @@ export class NetworkRequestCommandHandler implements CommandHandler { const commandToPost = { type: "networkRequestResponse", - payload: request.response, + payload: request.response as XMLHttpRequestResponseType, }; executeCommand(commandToPost); diff --git a/src/commands-setup/handleCommand.ts b/src/commands-setup/handleCommand.ts index fa23bbb..e27859f 100644 --- a/src/commands-setup/handleCommand.ts +++ b/src/commands-setup/handleCommand.ts @@ -19,7 +19,9 @@ export async function handleCommand(command: Command): Promise { await commandHandler.handle(command); } catch (error) { notifyErrorToEndUser( - `"${error}" executing the command \`${command.type}\`. This command is mapped to a class in the \`CommandsMapping.ts\` file. It could be a good starting point to look for the bug 😊` + `"${error as string}" executing the command \`${ + command.type + }\`. This command is mapped to a class in the \`CommandsMapping.ts\` file. It could be a good starting point to look for the bug 😊` ); } finally { const isACommandInsideAnotherCommand = command.type === "networkRequest"; @@ -37,6 +39,8 @@ function notifyErrorToEndUser(errorMessage: string): void { ); console.error( - `🫣️ Error in Figma plugin "${manifest.name}"\r\nFigma Plugin ID: "${figma.pluginId}"\r\n\r\n${errorMessage}.` + `🫣️ Error in Figma plugin "${manifest.name}"\r\nFigma Plugin ID: "${ + figma.pluginId ?? "" + }"\r\n\r\n${errorMessage}.` ); } diff --git a/src/figma-entrypoint.ts b/src/figma-entrypoint.ts index 670c1db..e803f7e 100644 --- a/src/figma-entrypoint.ts +++ b/src/figma-entrypoint.ts @@ -6,7 +6,7 @@ registerPluginMenuCommandParametersSuggestions(); registerPluginUiCommandHandlers(); function registerPluginMenuCommandHandlers() { - figma.on("run", async (event: RunEvent) => { + figma.on("run", (event: RunEvent) => { const hasToAccessPluginIframe = event.command === "showUi"; if (hasToAccessPluginIframe) { figma.showUI(__html__, { themeColors: true }); @@ -22,19 +22,20 @@ function registerPluginMenuCommandHandlers() { payload: event.parameters, }; - await handleCommand(command); + handleCommand(command); }); } function registerPluginMenuCommandParametersSuggestions() { - figma.parameters.on("input", async ({ key, query, result }: ParameterInputEvent) => { + figma.parameters.on("input", ({ key, query, result }: ParameterInputEvent) => { switch (key) { - case "typeOfShapes": + case "typeOfShapes": { const shapes = ["Rectangle", "Ellipse"]; const queryMatchingShapes = shapes.filter((s) => s.startsWith(query)); result.setSuggestions(queryMatchingShapes); break; + } default: break; } @@ -42,8 +43,9 @@ function registerPluginMenuCommandParametersSuggestions() { } function registerPluginUiCommandHandlers() { - figma.ui.onmessage = async (command: CommandType) => - await handleCommand(command); + figma.ui.onmessage = (command: CommandType) => { + handleCommand(command); + }; } function createInvisibleUiForBrowserApiAccess() { diff --git a/src/scene-commands/cancel/CancelCommandHandler.ts b/src/scene-commands/cancel/CancelCommandHandler.ts index cf9c066..86dce9f 100644 --- a/src/scene-commands/cancel/CancelCommandHandler.ts +++ b/src/scene-commands/cancel/CancelCommandHandler.ts @@ -5,7 +5,7 @@ export class CancelCommandHandler implements CommandHandler { constructor(private readonly figma: PluginAPI) {} // `command` argument needed due to polymorphism. - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars handle(command: CancelCommand): void { this.figma.notify("👋 Good bye!"); } diff --git a/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts b/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts index 9bc0d4a..0748207 100644 --- a/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts +++ b/src/scene-commands/paint-current-user-avatar/PaintCurrentUserAvatarCommandHandler.ts @@ -1,4 +1,5 @@ import { NetworkRequestCommand } from "../../browser-commands/network-request/NetworkRequestCommand"; +import { Command } from "../../commands-setup/Command"; import { CommandHandler } from "../../commands-setup/CommandHandler"; import { executeCommand } from "../../commands-setup/executeCommand"; import { PaintCurrentUserAvatarCommand } from "./PaintCurrentUserAvatarCommand"; @@ -11,7 +12,7 @@ export class PaintCurrentUserAvatarCommandHandler constructor(private readonly figma: PluginAPI) {} // `command` argument needed due to polymorphism. - // eslint-disable-next-line @typescript-eslint/no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars async handle(command: PaintCurrentUserAvatarCommand): Promise { const currentUserAvatarUrl = this.figma.currentUser?.photoUrl; const currentUserName = this.figma.currentUser?.name; @@ -25,12 +26,13 @@ export class PaintCurrentUserAvatarCommandHandler const responseType = "arraybuffer"; executeCommand(new NetworkRequestCommand(currentUserAvatarUrl, responseType)); - return new Promise((resolve) => { - this.figma.ui.onmessage = async (command) => { + return new Promise((resolve, reject) => { + this.figma.ui.onmessage = (command: Command) => { this.ensureToOnlyReceiveNetworkRequestResponse(command); - await this.createAvatarBadge(command.payload as ArrayBuffer, currentUserName as string); - resolve(); + this.createAvatarBadge(command.payload as ArrayBuffer, currentUserName as string) + .then(() => resolve()) + .catch(reject); }; }); } diff --git a/src/ui/register-ui-command-handlers.ts b/src/ui/register-ui-command-handlers.ts index 6469346..1f6b5ff 100644 --- a/src/ui/register-ui-command-handlers.ts +++ b/src/ui/register-ui-command-handlers.ts @@ -1,7 +1,12 @@ +import { Command } from "../commands-setup/Command"; import { handleCommand } from "../commands-setup/handleCommand"; -export function registerUiCommandHandlers() { - window.onmessage = async (event: MessageEvent) => { +export function registerUiCommandHandlers(): void { + window.onmessage = async ( + event: MessageEvent<{ + pluginMessage: Command; + }> + ) => { const command = { type: event.data.pluginMessage.type, payload: event.data.pluginMessage.payload, diff --git a/src/ui/register-ui-event-listeners.ts b/src/ui/register-ui-event-listeners.ts index f786dc2..35afd51 100644 --- a/src/ui/register-ui-event-listeners.ts +++ b/src/ui/register-ui-event-listeners.ts @@ -7,16 +7,18 @@ export function registerUiEventListeners(): void { const target = event.target as HTMLElement; switch (target.id) { - case "create": + case "create": { const textBox = document.getElementById("count") as HTMLInputElement; const countBase = 10; const count = parseInt(textBox.value, countBase); executeCommand(new CreateShapesCommand(count)); break; - case "cancel": + } + case "cancel": { executeCommand(new CancelCommand()); break; + } } }); } diff --git a/tests/.eslintrc b/tests/.eslintrc index 219143d..e46fa1f 100644 --- a/tests/.eslintrc +++ b/tests/.eslintrc @@ -2,5 +2,9 @@ "plugins": ["jest"], "env": { "jest/globals": true - } + }, + "rules": { + "@typescript-eslint/unbound-method": "off", + "jest/unbound-method": "error", + }, } From 9d7ab015cf953d6774face4d8bb4780c8872f388 Mon Sep 17 00:00:00 2001 From: Nuria Date: Wed, 8 Feb 2023 17:08:13 +0100 Subject: [PATCH 3/4] docs: update readme --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 02a0821..6968c40 100644 --- a/README.md +++ b/README.md @@ -306,10 +306,9 @@ it to the end user in a very friendly way 😇: - [TypeScript](https://typescriptlang.org) (v4) - [Prettier](https://prettier.io) - [Webpack](https://webpack.js.org) -- [ESLint](https://eslint.org) with: - - [Simple Import Sort](https://github.com/lydell/eslint-plugin-simple-import-sort) - - [Import plugin](https://github.com/benmosher/eslint-plugin-import) - - And a few other ES2015+ related rules +- [ESLint](https://eslint.org/) with: + - [Codely's config](https://github.com/lydell/eslint-plugin-simple-import-sort/) (includes ESLint's recommended rules, Prettier, Import plugin and more) + - [Jest plugin](https://www.npmjs.com/package/eslint-plugin-jest) - [Jest](https://jestjs.io) with [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro) - [GitHub Action workflows](https://github.com/CodelyTV/figma-plugin-skeleton/actions) set up to run tests and linting on push From 6d7c0925b76ec27f5c5bef843fd5970f33c15eca Mon Sep 17 00:00:00 2001 From: Nuria Date: Wed, 8 Feb 2023 17:08:37 +0100 Subject: [PATCH 4/4] docs: update readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 6968c40..9a81cfc 100644 --- a/README.md +++ b/README.md @@ -304,7 +304,6 @@ it to the end user in a very friendly way 😇: ### 🧰 Tooling already configured - [TypeScript](https://typescriptlang.org) (v4) -- [Prettier](https://prettier.io) - [Webpack](https://webpack.js.org) - [ESLint](https://eslint.org/) with: - [Codely's config](https://github.com/lydell/eslint-plugin-simple-import-sort/) (includes ESLint's recommended rules, Prettier, Import plugin and more)