From 2100218891f99613a1c6f4899c0d43be2626073c Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Wed, 17 Jul 2024 21:37:12 -0400 Subject: [PATCH 01/25] first plugin --- package-lock.json | 1258 +++++++++++++++++--------- package.json | 4 +- tools/bs-plugins/asynctask-plugin.ts | 82 +- 3 files changed, 894 insertions(+), 450 deletions(-) diff --git a/package-lock.json b/package-lock.json index f563f4f9d..da81ab3bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,13 @@ "version": "0.24.6", "hasInstallScript": true, "devDependencies": { - "@rokucommunity/bslint": "^0.8.21", + "@rokucommunity/bslint": "1.0.0-alpha.33", "@types/crypto-js": "^4.2.2", "@types/fs-extra": "^11.0.4", "@types/node": "^20.14.10", "@types/xml2js": "^0.4.14", "argparse": "^2.0.1", - "brighterscript": "0.67.3", + "brighterscript": "1.0.0-alpha.33", "brighterscript-formatter": "^1.7.3", "convert-svg-to-png": "^0.6.4", "cross-fetch": "^4.0.0", @@ -43,9 +43,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -83,98 +83,19 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -289,21 +210,23 @@ "dev": true }, "node_modules/@rokucommunity/bslint": { - "version": "0.8.21", - "resolved": "https://registry.npmjs.org/@rokucommunity/bslint/-/bslint-0.8.21.tgz", - "integrity": "sha512-gPLddRR/MKoyKoy4sNo/q7HgWrn9AquV9XC66+SwtiepMThjltNk59teJFfX5D0/jqrDnmY/XuXoOLXhvLp/Eg==", + "version": "1.0.0-alpha.33", + "resolved": "https://registry.npmjs.org/@rokucommunity/bslint/-/bslint-1.0.0-alpha.33.tgz", + "integrity": "sha512-6OKUCTlB5H5+6LMlrFjIGQZ1mm2IaLnfwVU6+4zbGCFde9Ta5eqGo6v80SqcC8LfaVeqmgRAfdWSXLfUIzQo/w==", "dev": true, "dependencies": { + "coveralls-next": "^4.2.0", "fs-extra": "^10.0.0", "jsonc-parser": "^2.3.0", "minimatch": "^3.0.4", + "vscode-languageserver-types": "^3.17.3", "yargs": "^15.4.1" }, "bin": { "bslint": "dist/cli.js" }, "peerDependencies": { - "brighterscript": ">= 0.59.0 < 1" + "brighterscript": "1.0.0-alpha.30" } }, "node_modules/@rokucommunity/bslint/node_modules/fs-extra": { @@ -459,9 +382,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -499,9 +422,9 @@ } }, "node_modules/@types/jsonfile": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz", - "integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", "dev": true, "dependencies": { "@types/node": "*" @@ -532,9 +455,9 @@ } }, "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, "optional": true, "dependencies": { @@ -573,9 +496,9 @@ } }, "node_modules/acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -585,10 +508,13 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -606,9 +532,9 @@ } }, "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -645,12 +571,15 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -754,9 +683,9 @@ } }, "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", + "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==", "dev": true }, "node_modules/balanced-match": { @@ -795,12 +724,15 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { @@ -828,6 +760,15 @@ "node": ">= 6" } }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/bluebird": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", @@ -875,21 +816,21 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/brighterscript": { - "version": "0.67.3", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.67.3.tgz", - "integrity": "sha512-uuAIvDmIENA+HdeuRiC1KM+n250m0J9k0Cdiwpby4cBZiFAHRkYoynEqmL8kwAaPtxdXI5RcZU4JqInCd1avlA==", + "version": "1.0.0-alpha.33", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-1.0.0-alpha.33.tgz", + "integrity": "sha512-6WAOg1zto5LrbErDlJPY6qwVjQFlmlcHyBXTBN31bbCllzqlrOASBJh9pUQtTLYifQUPB/wgN7h83lKksDJq6Q==", "dev": true, "dependencies": { "@rokucommunity/bslib": "^0.1.1", @@ -900,6 +841,7 @@ "chevrotain": "^7.0.1", "chokidar": "^3.5.1", "clear": "^0.1.0", + "coveralls-next": "^4.2.0", "cross-platform-clear-console": "^2.3.0", "debounce-promise": "^3.1.0", "eventemitter3": "^4.0.0", @@ -918,6 +860,8 @@ "roku-deploy": "^3.12.0", "serialize-error": "^7.0.1", "source-map": "^0.7.4", + "thenby": "^1.3.4", + "uuid": "^9.0.0", "vscode-languageserver": "^9.0.1", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", @@ -947,6 +891,15 @@ "bsfmt": "dist/cli.js" } }, + "node_modules/brighterscript-formatter/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/brighterscript-formatter/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -962,6 +915,94 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/brighterscript-formatter/node_modules/brighterscript": { + "version": "0.67.3", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.67.3.tgz", + "integrity": "sha512-uuAIvDmIENA+HdeuRiC1KM+n250m0J9k0Cdiwpby4cBZiFAHRkYoynEqmL8kwAaPtxdXI5RcZU4JqInCd1avlA==", + "dev": true, + "dependencies": { + "@rokucommunity/bslib": "^0.1.1", + "@rokucommunity/logger": "^0.3.9", + "@xml-tools/parser": "^1.0.7", + "array-flat-polyfill": "^1.0.1", + "chalk": "^2.4.2", + "chevrotain": "^7.0.1", + "chokidar": "^3.5.1", + "clear": "^0.1.0", + "cross-platform-clear-console": "^2.3.0", + "debounce-promise": "^3.1.0", + "eventemitter3": "^4.0.0", + "fast-glob": "^3.2.12", + "file-url": "^3.0.0", + "fs-extra": "^8.1.0", + "jsonc-parser": "^2.3.0", + "long": "^3.2.0", + "luxon": "^2.5.2", + "minimatch": "^3.0.4", + "moment": "^2.23.0", + "p-settle": "^2.1.0", + "parse-ms": "^2.1.0", + "readline": "^1.3.0", + "require-relative": "^0.8.7", + "roku-deploy": "^3.12.0", + "serialize-error": "^7.0.1", + "source-map": "^0.7.4", + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-protocol": "^3.17.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-languageserver-types": "^3.17.5", + "vscode-uri": "^3.0.8", + "xml2js": "^0.5.0", + "yargs": "^16.2.0" + }, + "bin": { + "bsc": "dist/cli.js" + } + }, + "node_modules/brighterscript-formatter/node_modules/brighterscript/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/brighterscript-formatter/node_modules/brighterscript/node_modules/jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "dev": true + }, + "node_modules/brighterscript-formatter/node_modules/brighterscript/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/brighterscript-formatter/node_modules/brighterscript/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/brighterscript-formatter/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -994,12 +1035,76 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/brighterscript-formatter/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/brighterscript-formatter/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/brighterscript-formatter/node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true }, + "node_modules/brighterscript-formatter/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/brighterscript-formatter/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brighterscript-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brighterscript-formatter/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/brighterscript-formatter/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -1017,6 +1122,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/brighterscript-formatter/node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/brighterscript-formatter/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -1053,6 +1171,15 @@ "node": ">=12" } }, + "node_modules/brighterscript/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/brighterscript/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1097,6 +1224,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/brighterscript/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/brighterscript/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -1120,6 +1253,32 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/brighterscript/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brighterscript/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/brighterscript/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -1348,16 +1507,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1370,6 +1523,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -1380,24 +1536,112 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, - "node_modules/clear": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/clear/-/clear-0.1.0.tgz", - "integrity": "sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==", + "node_modules/clear": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/clear/-/clear-0.1.0.tgz", + "integrity": "sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/color-convert": { @@ -1457,6 +1701,42 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1572,6 +1852,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -1666,6 +1947,25 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/coveralls-next": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/coveralls-next/-/coveralls-next-4.2.1.tgz", + "integrity": "sha512-O/SBGZsCryt+6Q3NuJHENyQYaucTEV9qp0KGaed+y42PUh+GuF949LRLHKZbxWwOIc1tV8bJRIVWlfbZ8etEwQ==", + "dev": true, + "dependencies": { + "form-data": "4.0.0", + "js-yaml": "4.1.0", + "lcov-parse": "1.0.0", + "log-driver": "1.2.7", + "minimist": "1.2.8" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -1773,9 +2073,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", "dev": true }, "node_modules/debounce-promise": { @@ -1961,9 +2261,9 @@ "dev": true }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "node_modules/encodeurl": { @@ -1975,40 +2275,15 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/encoding-japanese": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", - "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.1.0.tgz", + "integrity": "sha512-58XySVxUgVlBikBTbQ8WdDxBDHIdXucB16LO5PBHR8t75D54wQrNo4cg+58+R1CtJfKnsVsvt9XlteRaR8xw1w==", "dev": true, "engines": { "node": ">=8.10.0" } }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -2052,9 +2327,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -2159,9 +2434,9 @@ } }, "node_modules/extract-zip/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2246,9 +2521,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -2289,9 +2564,9 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, "dependencies": { "cross-spawn": "^7.0.0", @@ -2304,18 +2579,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2325,6 +2588,20 @@ "node": "*" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2370,9 +2647,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -2496,6 +2773,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -2619,18 +2897,6 @@ "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2677,9 +2943,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -2776,9 +3042,9 @@ } }, "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2843,30 +3109,6 @@ "node": ">=0.8.0" } }, - "node_modules/imap/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/imap/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/imap/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -2877,6 +3119,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { "once": "^1.3.0", @@ -2926,12 +3169,15 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2983,9 +3229,9 @@ "dev": true }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, "node_modules/isexe": { @@ -3018,6 +3264,18 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -3099,6 +3357,51 @@ "setimmediate": "^1.0.5" } }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==", + "dev": true, + "bin": { + "lcov-parse": "bin/cli.js" + } + }, "node_modules/leac": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", @@ -3109,9 +3412,9 @@ } }, "node_modules/libbase64": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz", - "integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", + "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==", "dev": true }, "node_modules/libmime": { @@ -3126,15 +3429,6 @@ "libqp": "2.1.0" } }, - "node_modules/libmime/node_modules/encoding-japanese": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.1.0.tgz", - "integrity": "sha512-58XySVxUgVlBikBTbQ8WdDxBDHIdXucB16LO5PBHR8t75D54wQrNo4cg+58+R1CtJfKnsVsvt9XlteRaR8xw1w==", - "dev": true, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/libmime/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -3147,24 +3441,12 @@ "node": ">=0.10.0" } }, - "node_modules/libmime/node_modules/libbase64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", - "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==", - "dev": true - }, - "node_modules/libmime/node_modules/libqp": { + "node_modules/libqp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.0.tgz", "integrity": "sha512-O6O6/fsG5jiUVbvdgT7YX3xY3uIadR6wEZ7+vy9u7PKHAlSEB6blvC1o5pHBjgsi95Uo0aiBBdkyFecj6jtb7A==", "dev": true }, - "node_modules/libqp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.0.1.tgz", - "integrity": "sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==", - "dev": true - }, "node_modules/lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -3213,6 +3495,15 @@ "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", "dev": true }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true, + "engines": { + "node": ">=0.8.6" + } + }, "node_modules/long": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", @@ -3258,15 +3549,6 @@ "tlds": "1.252.0" } }, - "node_modules/mailparser/node_modules/encoding-japanese": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.1.0.tgz", - "integrity": "sha512-58XySVxUgVlBikBTbQ8WdDxBDHIdXucB16LO5PBHR8t75D54wQrNo4cg+58+R1CtJfKnsVsvt9XlteRaR8xw1w==", - "dev": true, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/mailparser/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -3290,6 +3572,15 @@ "libqp": "2.0.1" } }, + "node_modules/mailsplit/node_modules/encoding-japanese": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", + "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==", + "dev": true, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/mailsplit/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -3302,6 +3593,12 @@ "node": ">=0.10.0" } }, + "node_modules/mailsplit/node_modules/libbase64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz", + "integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==", + "dev": true + }, "node_modules/mailsplit/node_modules/libmime": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.2.0.tgz", @@ -3314,6 +3611,12 @@ "libqp": "2.0.1" } }, + "node_modules/mailsplit/node_modules/libqp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.0.1.tgz", + "integrity": "sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==", + "dev": true + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -3354,12 +3657,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -3478,9 +3781,9 @@ "dev": true }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -3517,9 +3820,9 @@ } }, "node_modules/node-html-to-image/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -3567,6 +3870,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -3618,7 +3922,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz", "integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==", - "deprecated": "< 21.5.0 is no longer supported", + "deprecated": "< 22.6.4 is no longer supported", "dev": true, "hasInstallScript": true, "dependencies": { @@ -3641,6 +3945,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -3650,9 +3955,9 @@ } }, "node_modules/node-html-to-image/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", "dev": true, "dependencies": { "async-limiter": "~1.0.0" @@ -3698,10 +4003,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3981,9 +4289,9 @@ "dev": true }, "node_modules/postman-request": { - "version": "2.88.1-postman.33", - "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.33.tgz", - "integrity": "sha512-uL9sCML4gPH6Z4hreDWbeinKU0p0Ke261nU7OvII95NU22HN6Dk7T/SaVPaj6T4TsQqGKIFw6/woLZnH7ugFNA==", + "version": "2.88.1-postman.34", + "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.34.tgz", + "integrity": "sha512-GkolJ4cIzgamcwHRDkeZc/taFWO1u2HuGNML47K9ZAsFH2LdEkS5Yy8QanpzhjydzV3WWthl9v60J8E7SjKodQ==", "dev": true, "dependencies": { "@postman/form-data": "~3.1.1", @@ -4022,6 +4330,15 @@ "node": ">=0.6" } }, + "node_modules/postman-request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4094,7 +4411,7 @@ "version": "13.7.0", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.7.0.tgz", "integrity": "sha512-U1uufzBjz3+PkpCxFrWzh4OrMIdIb2ztzCu0YEPfRHjHswcSwHZswnK+WdsOQJsRV8WeTg3jLhJR4D867+fjsA==", - "deprecated": "< 19.4.0 is no longer supported", + "deprecated": "< 22.6.4 is no longer supported", "dev": true, "hasInstallScript": true, "dependencies": { @@ -4233,26 +4550,17 @@ } }, "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4323,12 +4631,12 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -4353,6 +4661,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -4368,6 +4677,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -4589,9 +4899,9 @@ "dev": true }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "dev": true }, "node_modules/selderee": { @@ -4685,17 +4995,17 @@ "dev": true }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4755,6 +5065,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -4789,6 +5100,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -4842,32 +5165,26 @@ } }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -4885,7 +5202,22 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -4897,6 +5229,21 @@ "node": ">=8" } }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", @@ -4910,6 +5257,15 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4976,6 +5332,15 @@ "node": ">= 6" } }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -4985,6 +5350,12 @@ "node": ">=8" } }, + "node_modules/thenby": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", + "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", + "dev": true + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -5001,15 +5372,12 @@ } }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/to-regex-range": { @@ -5133,15 +5501,15 @@ } }, "node_modules/uc.micro": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.0.0.tgz", - "integrity": "sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", + "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", "dev": true, "optional": true, "bin": { @@ -5174,9 +5542,9 @@ "dev": true }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -5244,10 +5612,14 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -5380,17 +5752,20 @@ "dev": true }, "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi-cjs": { @@ -5411,6 +5786,15 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -5444,38 +5828,49 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, "node_modules/wrappy": { "version": "1.0.2", @@ -5579,6 +5974,47 @@ "node": ">=6" } }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 159a8d48c..5d84e0a80 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,13 @@ "version": "0.24.6", "description": "Unofficial YouTube client for Roku", "devDependencies": { - "@rokucommunity/bslint": "^0.8.21", + "@rokucommunity/bslint": "1.0.0-alpha.33", "@types/crypto-js": "^4.2.2", "@types/fs-extra": "^11.0.4", "@types/node": "^20.14.10", "@types/xml2js": "^0.4.14", "argparse": "^2.0.1", - "brighterscript": "0.67.3", + "brighterscript": "1.0.0-alpha.33", "brighterscript-formatter": "^1.7.3", "convert-svg-to-png": "^0.6.4", "cross-fetch": "^4.0.0", diff --git a/tools/bs-plugins/asynctask-plugin.ts b/tools/bs-plugins/asynctask-plugin.ts index fe64104eb..c7049bd91 100644 --- a/tools/bs-plugins/asynctask-plugin.ts +++ b/tools/bs-plugins/asynctask-plugin.ts @@ -1,77 +1,85 @@ // This plugin generates a task component for each function annotated with @asynctask import { - CompilerPlugin, + AfterFileAddEvent, + BeforeProgramValidateEvent, + BrsFile, BscFile, - isBrsFile, - WalkMode, + CompilerPlugin, createVisitor, - Program, - FunctionStatement, DiagnosticSeverity, + FunctionStatement, + isBrsFile, + ParseMode, + Program, + WalkMode, + XmlFile, } from 'brighterscript'; export class AsyncTaskPlugin implements CompilerPlugin { public name = 'AsyncTaskPlugin'; - afterFileParse(file: BscFile) { - if (!isBrsFile(file)) { - return + afterFileAdd(event: AfterFileAddEvent) { + if (!isBrsFile(event.file)) { + return; } - const program = file.program + const program = event.program; - file.ast.walk(createVisitor({ - FunctionExpression: (func) => { - if (!this.isAsyncTask(func.functionStatement)) { - return + event.file.ast.walk(createVisitor({ + FunctionStatement: (funcStmt) => { + if (!this.isAsyncTask(funcStmt)) { + return; } - const functionName = func.functionStatement!.name.text - const hasParams = func.functionStatement!.func.parameters.length > 0 - const taskName = `${functionName}_AsyncTask` + const functionName = funcStmt.getName(ParseMode.BrightScript); + const hasParams = funcStmt.func.parameters.length > 0; + const taskName = `${functionName}_AsyncTask`; + + const bs = this.generateBsTask(functionName, hasParams, event.file); + const bsFile = `components/AsyncTask/generated/${taskName}.bs`; - const bs = this.generateBsTask(functionName, hasParams, file) - const bsFile = `components/AsyncTask/generated/${taskName}.bs` + const xml = this.generateXmlTask(taskName, bsFile); + const xmlFile = `components/AsyncTask/generated/${taskName}.xml`; - const xml = this.generateXmlTask(taskName, bsFile) - const xmlFile = `components/AsyncTask/generated/${taskName}.xml` + // clear existing diagnostics + program.diagnostics.clearByFilter({ file: event.file, tag: this.name }); if (program.hasFile(xmlFile)) { - const currentContent = program.getFile(xmlFile).fileContents + const currentContent = (program.getFile(xmlFile) as XmlFile).fileContents; if (currentContent !== xml) { - file.addDiagnostics([{ - file: file, - range: func.range, + program.diagnostics.register({ + file: event.file, + range: funcStmt.tokens.name.location.range, message: `AsyncTaskPlugin: file ${xmlFile} already exists`, severity: DiagnosticSeverity.Error, code: 'ASYNC_TASK_FILE_EXISTS', - }]); + }, { tags: [this.name] }); } } - file.program.setFile(xmlFile, xml) + program.setFile(xmlFile, xml); if (program.hasFile(bsFile)) { - const currentContent = program.getFile(bsFile).fileContents + const currentContent = (program.getFile(bsFile) as BrsFile).fileContents; if (currentContent !== bs) { - file.addDiagnostics([{ - file: file, - range: func.range, + program.diagnostics.register({ + file: event.file, + range: funcStmt.tokens.name.location.range, message: `AsyncTaskPlugin: file ${bsFile} already exists`, severity: DiagnosticSeverity.Error, code: 'ASYNC_TASK_FILE_EXISTS', - }]); + }, { tags: [this.name] }); } } - file.program.setFile(bsFile, bs) - }, + program.setFile(bsFile, bs); + } }), { - walkMode: WalkMode.visitExpressionsRecursive + walkMode: WalkMode.visitStatements }); } - beforeProgramValidate(program: Program) { - this.generateTaskListEnum(program); + beforeProgramValidate(event: BeforeProgramValidateEvent) { + this.generateTaskListEnum(event.program); } isAsyncTask(functionStatement: FunctionStatement | undefined) { @@ -153,7 +161,7 @@ end function return } - acc.add(func.functionStatement!.name.text) + acc.add(func.functionStatement!.getName(ParseMode.BrightScript)) }, }), { walkMode: WalkMode.visitExpressionsRecursive From f32b91a84b7cc0b4cf8ff5df71ab9635a2b0af76 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Wed, 17 Jul 2024 22:07:47 -0400 Subject: [PATCH 02/25] type gen plugin --- tools/bs-plugins/type-gen-plugin.ts | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tools/bs-plugins/type-gen-plugin.ts b/tools/bs-plugins/type-gen-plugin.ts index 538c7ca2c..28a44ab3f 100644 --- a/tools/bs-plugins/type-gen-plugin.ts +++ b/tools/bs-plugins/type-gen-plugin.ts @@ -1,5 +1,5 @@ // This plugin generates a file containing functions for type checking and type casting. -import { CompilerPlugin, Program, SourceObj } from "brighterscript"; +import { BeforeProvideFileEvent, CompilerPlugin } from "brighterscript"; const types = [ { name: 'Bool', interface: 'ifBoolean', type: 'boolean', defaultValue: 'false' }, @@ -38,18 +38,13 @@ end function`; export class TypeGenPlugin implements CompilerPlugin { public name = 'TypeGenPlugin'; - program: Program | undefined; - - afterProgramCreate(program: Program) { - this.program = program; - } - - beforeFileParse(source: SourceObj) { - if (!source.srcPath.endsWith(typesFilePath)) { + beforeProvideFile(event: BeforeProvideFileEvent) { + if (!event.srcPath.endsWith(typesFilePath)) { return; } - if (source.source.includes(generatedCodeHeader)) { + let content = event.data.value.toString(); + if (content.includes(generatedCodeHeader)) { return; } @@ -62,8 +57,15 @@ export class TypeGenPlugin implements CompilerPlugin { } }); - const fileContents = source.source + generatedCode; - this.program!.setFile(source.srcPath, fileContents) + content += generatedCode; + + const file = event.fileFactory.BrsFile({ + srcPath: event.srcPath, + destPath: event.destPath, + }); + file.fileContents = content; + + event.files.push(file); } } From 6eb6dc9bef53e9fed2c1ecf24c8aac176f3f7d81 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Thu, 18 Jul 2024 12:40:33 -0400 Subject: [PATCH 03/25] async task plugin --- tools/bs-plugins/asynctask-plugin.ts | 59 ++++++++++++++++------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/tools/bs-plugins/asynctask-plugin.ts b/tools/bs-plugins/asynctask-plugin.ts index c7049bd91..f6b3c99b9 100644 --- a/tools/bs-plugins/asynctask-plugin.ts +++ b/tools/bs-plugins/asynctask-plugin.ts @@ -25,53 +25,52 @@ export class AsyncTaskPlugin implements CompilerPlugin { } const program = event.program; - event.file.ast.walk(createVisitor({ FunctionStatement: (funcStmt) => { if (!this.isAsyncTask(funcStmt)) { return; } - const functionName = funcStmt.getName(ParseMode.BrightScript); + const functionName = this.getFunctionName(funcStmt); const hasParams = funcStmt.func.parameters.length > 0; - const taskName = `${functionName}_AsyncTask`; + const taskName = this.getTaskName(funcStmt); - const bs = this.generateBsTask(functionName, hasParams, event.file); - const bsFile = `components/AsyncTask/generated/${taskName}.bs`; + const bsFileContent = this.generateBsTask(functionName, hasParams, event.file); + const bsFilePath = `components/AsyncTask/generated/${taskName}.bs`; - const xml = this.generateXmlTask(taskName, bsFile); - const xmlFile = `components/AsyncTask/generated/${taskName}.xml`; + const xmlFileContent = this.generateXmlTask(taskName); + const xmlFilePath = `components/AsyncTask/generated/${taskName}.xml`; - // clear existing diagnostics program.diagnostics.clearByFilter({ file: event.file, tag: this.name }); - if (program.hasFile(xmlFile)) { - const currentContent = (program.getFile(xmlFile) as XmlFile).fileContents; - if (currentContent !== xml) { + if (program.hasFile(xmlFilePath)) { + const currentContent = (program.getFile(xmlFilePath) as XmlFile).fileContents; + if (currentContent !== xmlFileContent) { program.diagnostics.register({ file: event.file, range: funcStmt.tokens.name.location.range, - message: `AsyncTaskPlugin: file ${xmlFile} already exists`, + message: `AsyncTaskPlugin: file ${xmlFilePath} already exists`, severity: DiagnosticSeverity.Error, code: 'ASYNC_TASK_FILE_EXISTS', }, { tags: [this.name] }); } } - program.setFile(xmlFile, xml); - if (program.hasFile(bsFile)) { - const currentContent = (program.getFile(bsFile) as BrsFile).fileContents; - if (currentContent !== bs) { + if (program.hasFile(bsFilePath)) { + const currentContent = (program.getFile(bsFilePath) as BrsFile).fileContents; + if (currentContent !== bsFileContent) { program.diagnostics.register({ file: event.file, range: funcStmt.tokens.name.location.range, - message: `AsyncTaskPlugin: file ${bsFile} already exists`, + message: `AsyncTaskPlugin: file ${bsFilePath} already exists`, severity: DiagnosticSeverity.Error, code: 'ASYNC_TASK_FILE_EXISTS', }, { tags: [this.name] }); } } - program.setFile(bsFile, bs); + + event.program.setFile(xmlFilePath, xmlFileContent); + event.program.setFile(bsFilePath, bsFileContent); } }), { walkMode: WalkMode.visitStatements @@ -96,9 +95,17 @@ export class AsyncTaskPlugin implements CompilerPlugin { return false } + getFunctionName(funcStmt: FunctionStatement) { + return funcStmt.getName(ParseMode.BrightScript); + } + + getTaskName(funcStmt: FunctionStatement) { + return this.getFunctionName(funcStmt) + '_AsyncTask'; + } + generateBsTask(functionName: string, hasInput: boolean, file: BscFile): string { return ` -import "pkg:/${file.pkgPath}" +import "pkg:/${file.destPath}" import "pkg:/source/utils/ErrorUtils.bs" function Init() @@ -135,7 +142,7 @@ end function ` } - generateXmlTask(taskName: string, bsFile: string): string { + generateXmlTask(taskName: string): string { return ` @@ -156,22 +163,22 @@ end function } file.ast.walk(createVisitor({ - FunctionExpression: (func) => { - if (!this.isAsyncTask(func.functionStatement)) { + FunctionStatement: (funcStmt) => { + if (!this.isAsyncTask(funcStmt)) { return } - acc.add(func.functionStatement!.getName(ParseMode.BrightScript)) + acc.add(funcStmt) }, }), { - walkMode: WalkMode.visitExpressionsRecursive + walkMode: WalkMode.visitStatements }); return acc - }, new Set()); + }, new Set()); const enumItems = Array.from(asyncTasks).map((task) => { - return `${task} = "${task}_AsyncTask"` + return `${this.getFunctionName(task)} = "${this.getTaskName(task)}"` }) const content = 'enum Tasks\n ' + enumItems.join('\n ') + '\nend enum\n'; From cf8f4120d357e3358c8315156ad995007b53124b Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Thu, 18 Jul 2024 13:02:25 -0400 Subject: [PATCH 04/25] json yaml plugin --- tools/bs-plugins/json-yaml-plugin.ts | 51 +++++++++++++++++----------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/tools/bs-plugins/json-yaml-plugin.ts b/tools/bs-plugins/json-yaml-plugin.ts index f63b136ea..27e7523fb 100644 --- a/tools/bs-plugins/json-yaml-plugin.ts +++ b/tools/bs-plugins/json-yaml-plugin.ts @@ -1,10 +1,9 @@ // This plugin converts json5 and yaml files to json files import { - CompilerPlugin, FileObj, ProgramBuilder, util, + CompilerPlugin, + ProvideFileEvent, } from 'brighterscript'; -import path from 'path'; -import fs from 'fs-extra' import json5 from 'json5'; import YAML from "yaml"; @@ -14,28 +13,40 @@ const yamlExtensions = ['.yaml', '.yml']; export class JsonYamlPlugin implements CompilerPlugin { public name = 'JsonYamlPlugin'; - afterPrepublish(builder: ProgramBuilder, files: FileObj[]) { - const jsonFiles = files - .filter((file) => jsonExtensions.includes(path.extname(file.dest))) - .map((file) => path.join(builder.options.stagingDir!, file.dest)); + provideFile(event: ProvideFileEvent) { + if (jsonExtensions.includes(event.srcExtension)) { + this.handleJson(event); + } else if (yamlExtensions.includes(event.srcExtension)) { + this.handleYaml(event); + } + } - const yamlFiles = files - .filter((file) => yamlExtensions.includes(path.extname(file.dest))) - .map((file) => path.join(builder.options.stagingDir!, file.dest)); + handleJson(event: ProvideFileEvent) { + let contents = event.data.value.toString(); + const json = json5.parse(contents); + contents = JSON.stringify(json); - jsonFiles.forEach((filePath) => { - let contents = fs.readFileSync(filePath, 'utf8'); - const json = json5.parse(contents); - contents = JSON.stringify(json); - fs.writeFileSync(filePath, contents); + const file = event.fileFactory.AssetFile({ + srcPath: event.srcPath, + destPath: event.destPath, + data: contents, }); - yamlFiles.forEach((filePath) => { - let contents = fs.readFileSync(filePath, 'utf8'); - const yaml = YAML.parse(contents); - contents = JSON.stringify(yaml); - fs.writeFileSync(filePath, contents); + event.files.push(file); + } + + handleYaml(event: ProvideFileEvent) { + let contents = event.data.value.toString(); + const yaml = YAML.parse(contents); + contents = JSON.stringify(yaml); + + const file = event.fileFactory.AssetFile({ + srcPath: event.srcPath, + destPath: event.destPath, + data: contents, }); + + event.files.push(file); } } From 6e59f3a21d51af20601dd7dd26135c34c8ee2871 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Thu, 18 Jul 2024 13:06:48 -0400 Subject: [PATCH 05/25] validation plugin --- tools/bs-plugins/validation-plugin.ts | 33 +++++++++++++++------------ 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tools/bs-plugins/validation-plugin.ts b/tools/bs-plugins/validation-plugin.ts index 05a80acdf..2d30cdf29 100644 --- a/tools/bs-plugins/validation-plugin.ts +++ b/tools/bs-plugins/validation-plugin.ts @@ -2,10 +2,11 @@ // Rules are defined in the `validation` property of the `bsconfig.json` file. import { + BeforeProgramValidateEvent, BscFile, CompilerPlugin, + DiagnosticSeverity, OnFileValidateEvent, - Program, Range, isBrsFile } from 'brighterscript'; @@ -20,21 +21,21 @@ type Validation = { export class ValidationPlugin implements CompilerPlugin { public name = 'ValidationPlugin'; - private validation?: Validation[]; - - beforeProgramValidate(program: Program) { - // @ts-ignore - this.validation = program.options.validation as Validation[] | undefined; - } - onFileValidate(event: OnFileValidateEvent) { const file = event.file; + if (!isBrsFile(file)) { + return; + } - if (!this.validation || !isBrsFile(file)) { + // @ts-ignore + const validation = event.program.options.validation as Validation[] | undefined; + if (!validation) { return; } - this.validation.forEach((validation) => { + event.program.diagnostics.clearByFilter({ file: file, tag: this.name }); + + validation.forEach((validation) => { const regex = new RegExp(validation.regex, validation.regexFlags); const fileContents = file.fileContents; @@ -42,12 +43,14 @@ export class ValidationPlugin implements CompilerPlugin { while ((match = regex.exec(fileContents)) !== null) { const line = fileContents.substring(0, match.index).split('\n').length - 1; const column = match.index - fileContents.lastIndexOf('\n', match.index) - 1; - file.diagnostics.push({ - code: validation.code, - message: validation.message, + + event.program.diagnostics.register({ file: file, - range: Range.create(line, column, line, column + match[0].length) - }); + range: Range.create(line, column, line, column + match[0].length), + message: validation.message, + code: validation.code, + severity: DiagnosticSeverity.Error + }, { tags: [this.name] }); } }); } From 65fa6c15c6547fb62611e9c39e121b837164d845 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Thu, 18 Jul 2024 18:26:35 -0400 Subject: [PATCH 06/25] manifest edit plugin --- tools/bs-plugins/manifest-edit-plugin.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/bs-plugins/manifest-edit-plugin.ts b/tools/bs-plugins/manifest-edit-plugin.ts index 37bfe8386..fb61e7f31 100644 --- a/tools/bs-plugins/manifest-edit-plugin.ts +++ b/tools/bs-plugins/manifest-edit-plugin.ts @@ -8,10 +8,11 @@ // - This is only done when --debug is set import { + AfterBuildProgramEvent, + BeforeProgramCreateEvent, BeforeProgramDisposeEvent, CompilerPlugin, Program, - ProgramBuilder } from 'brighterscript'; import path from 'path'; import fs from 'fs'; @@ -22,7 +23,8 @@ export class ManifestEditPlugin implements CompilerPlugin { private originalManifestContent?: string; - beforeProgramCreate(builder: ProgramBuilder) { + beforeProgramCreate(event: BeforeProgramCreateEvent) { + const builder = event.builder; const manifestPath = path.join(builder.options.rootDir!, "manifest") let originalManifestContent = fs.readFileSync(manifestPath, { encoding: 'utf8', flag: 'r' }) @@ -52,8 +54,8 @@ export class ManifestEditPlugin implements CompilerPlugin { fs.writeFileSync(manifestPath, manifestContent) } - afterPublish(builder: ProgramBuilder) { - this.restoreManifest(builder.program!); + afterBuildProgram(event: AfterBuildProgramEvent) { + this.restoreManifest(event.program); } beforeProgramDispose(event: BeforeProgramDisposeEvent) { From 1ef94694f80a0f3d4fdf720784c9fac8d75434a8 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Thu, 18 Jul 2024 20:05:00 -0400 Subject: [PATCH 07/25] locale validation --- tools/bs-plugins/locale-validation-plugin.ts | 137 ++++++++++--------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/tools/bs-plugins/locale-validation-plugin.ts b/tools/bs-plugins/locale-validation-plugin.ts index 48416a3ce..b305631e0 100644 --- a/tools/bs-plugins/locale-validation-plugin.ts +++ b/tools/bs-plugins/locale-validation-plugin.ts @@ -7,12 +7,16 @@ // - For that reason, only certain attributes (like "text" and "title") are allowed to have localized values import { + AfterFileValidateEvent, + AfterProgramValidateEvent, + BeforeProgramValidateEvent, BrsFile, - BscFile, CompilerPlugin, DiagnosticSeverity, EnumStatement, + LiteralExpression, Program, + Range, WalkMode, XmlFile, createVisitor, @@ -33,8 +37,8 @@ export class LocaleValidationPlugin implements CompilerPlugin { private enums: { file: BrsFile, enumStatement: EnumStatement }[] = []; private localeValues: string[] = []; - beforeProgramValidate(program: Program) { - this.enums = this.getEnumsWithLocaleAnnotation(program); + beforeProgramValidate(event: BeforeProgramValidateEvent) { + this.enums = this.getEnumsWithLocaleAnnotation(event.program); if (this.enums.length === 0) { this.localeValues = []; return; @@ -43,7 +47,10 @@ export class LocaleValidationPlugin implements CompilerPlugin { this.localeValues = this.getLocaleValues(this.enums); } - afterFileValidate(file: BscFile) { + afterFileValidate(event: AfterFileValidateEvent) { + const file = event.file; + const program = event.program; + if (!isXmlFile(file)) { return; } @@ -52,81 +59,81 @@ export class LocaleValidationPlugin implements CompilerPlugin { return; } - if (!file.ast.component) { + if (!file.ast.componentElement) { return; } + program.diagnostics.clearByFilter({ file: file, tag: this.name }); + const localeValues = this.localeValues; - const component = file.ast.component; + const componentElement = file.ast.componentElement; + const fields = componentElement.interfaceElement?.fields; + const children = componentElement.childrenElement; - if (component.api && component.api.fields) { - component.api.fields.forEach((field) => { + if (fields) { + fields.forEach((field) => { const value = field.value; if (value && localeValues.includes(value)) { const id = field.id; if (!allowedXmlAttributes.includes(id)) { - file.addDiagnostics([{ + program.diagnostics.register({ file: file, - range: field.range!, + range: field.attributes.find((attr) => attr.key === 'value')?.tokens.value?.location?.range || field.tokens.startTagName.location!.range, message: `Locale value found in xml component "${value}" but the attribute "${id}" is not allowed to be localized.`, severity: DiagnosticSeverity.Error, code: 'LOCALE_VALUE_IN_XML', - }]); + }, { tags: [this.name] }); } } }); } - if (component.children) { - component.children.children.forEach((child) => { - this.validateSgNode(child, localeValues, file); + if (children) { + children.elements.forEach((child) => { + this.validateSgNode(program, child, localeValues, file); }); } } - validateSgNode(node: SGNode, localeValues: string[], file: XmlFile) { + validateSgNode(program: Program, node: SGNode, localeValues: string[], file: XmlFile) { node.attributes.forEach((attribute) => { - const value = attribute.value.text; + const value = attribute.value; if (value && localeValues.includes(value)) { - const key = attribute.key.text; + const key = attribute.key; if (!allowedXmlAttributes.includes(key)) { - file.addDiagnostics([{ + program.diagnostics.register({ file: file, - range: attribute.value.range!, + range: attribute.tokens.value!.location!.range, message: `Locale value found in xml component: "${value}" but the attribute "${key}" is not allowed to be localized.`, severity: DiagnosticSeverity.Error, code: 'LOCALE_VALUE_IN_XML', - }]); + }); } } }); - if (!node.children) { - return; - } - node.children.forEach((child) => { - this.validateSgNode(child, localeValues, file); + node.elements.forEach((child) => { + this.validateSgNode(program, child, localeValues, file); }); } - afterProgramValidate(program: Program) { + afterProgramValidate(event: AfterProgramValidateEvent) { if (this.enums.length === 0 || this.localeValues.length === 0) { return; } + const program = event.program; const uniqueLocaleValues = Array.from(new Set(this.localeValues)); if (uniqueLocaleValues.length !== this.localeValues.length) { const duplicates = this.localeValues.filter((value, index) => this.localeValues.indexOf(value) !== index); - program.addDiagnostics([{ + + program.diagnostics.register({ file: this.enums[0].file, - range: { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 } - }, + range: Range.create(0, 0, 0, 0), message: `Duplicate values in locale enums: ${duplicates.join(', ')}`, severity: DiagnosticSeverity.Error, code: 'LOCALE_DUPLICATE_VALUES', - }]); + }); } this.validateEnglishTranslations(program, this.localeValues, this.enums[0].file); @@ -135,8 +142,11 @@ export class LocaleValidationPlugin implements CompilerPlugin { const translationFiles = globSync(`locale/**/translations.ts`, { cwd: rootDir }); translationFiles.forEach((translationFile) => { const srcPath = pathJoin(rootDir, translationFile); - const pkgPath = pathJoin('pkg:/', translationFile); - const xmlFile = new XmlFile(srcPath, pkgPath, program); + const xmlFile = new XmlFile({ + srcPath: srcPath, + destPath: translationFile, + program: program, + }); this.validateTranslations(xmlFile, program, this.localeValues, this.enums[0].file); }); } @@ -149,24 +159,25 @@ export class LocaleValidationPlugin implements CompilerPlugin { const missingKeys = Object.keys(translations).filter((key) => !localeValues.includes(key)); if (missingKeys.length > 0) { - program.addDiagnostics([{ + + program.diagnostics.register({ file: file, - range: { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 } - }, - message: `Missing keys in enum from ${translationFile.srcPath}: ${missingKeys.join(', ')}`, + range: Range.create(0, 0, 0, 0), + message: `Missing keys in locale enum from ${translationFile.srcPath}: ${missingKeys.join(', ')}`, severity: DiagnosticSeverity.Error, code: 'LOCALE_MISSING_ENUM_KEYS', - }]); + }); } } validateEnglishTranslations(program: Program, localeValues: string[], file: BrsFile) { const translationFile = 'locale/en_US/translations.ts'; const srcPath = pathJoin(program.options.rootDir!, translationFile); - const pkgPath = pathJoin('pkg:/', translationFile); - const xmlFile = new XmlFile(srcPath, pkgPath, program); + const xmlFile = new XmlFile({ + srcPath: srcPath, + destPath: translationFile, + program: program, + }); const englishTranslations = this.loadTranslationsFile(program, xmlFile); if (!englishTranslations) { @@ -177,30 +188,25 @@ export class LocaleValidationPlugin implements CompilerPlugin { const mismatchedKeys = Object.keys(englishTranslations).filter((key) => englishTranslations[key] !== key); if (mismatchedKeys.length > 0) { const mismatchedTranslations = mismatchedKeys.map((key) => `${key}=${englishTranslations[key]}`); - program.addDiagnostics([{ + + program.diagnostics.register({ file: file, - range: { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 } - }, + range: Range.create(0, 0, 0, 0), message: `Mismatched translations in en_US: ${mismatchedTranslations.join(', ')}`, severity: DiagnosticSeverity.Error, code: 'LOCALE_MISMATCHED_EN_TRANSLATIONS', - }]); + }); } const missingLocaleValues = localeValues.filter((value) => !englishTranslations[value]); if (missingLocaleValues.length > 0) { - program.addDiagnostics([{ + program.diagnostics.register({ file: file, - range: { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 } - }, + range: Range.create(0, 0, 0, 0), message: `Missing translations in en_US: ${missingLocaleValues.join(', ')}`, severity: DiagnosticSeverity.Error, code: 'LOCALE_MISSING_TRANSLATIONS', - }]); + }); const xml = missingLocaleValues.reduce((acc, value) => { acc += ` @@ -230,16 +236,13 @@ export class LocaleValidationPlugin implements CompilerPlugin { const translation = message.translation[0]; if (acc[source]) { - program.addDiagnostics([{ + program.diagnostics.register({ file: translationFile, - range: { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 } - }, + range: Range.create(0, 0, 0, 0), message: `Duplicate translation key: ${source}`, severity: DiagnosticSeverity.Error, code: 'LOCALE_DUPLICATE_TRANSLATION_KEY', - }]); + }); } acc[source] = translation; @@ -264,15 +267,15 @@ export class LocaleValidationPlugin implements CompilerPlugin { return enums.reduce((acc, e) => { e.enumStatement.walk(createVisitor({ EnumMemberStatement: (enumMemberStatement) => { - const value = enumMemberStatement.getValue(); + const value = (enumMemberStatement.value as LiteralExpression).tokens.value.text; if (!value.startsWith('"') || !value.endsWith('"')) { - e.file.addDiagnostics([{ + e.file.program.diagnostics.register({ file: e.file, - range: enumMemberStatement.range, + range: enumMemberStatement.tokens.name.location.range, message: `Locale value should be a string literal`, severity: DiagnosticSeverity.Error, code: 'LOCALE_VALUE_NOT_STRING_LITERAL', - }]); + }); return; } acc.push(value.slice(1, -1)); @@ -289,8 +292,8 @@ export class LocaleValidationPlugin implements CompilerPlugin { if (!isBrsFile(file)) { return acc; } - if (file.fileContents.includes('@locale')) { - program.logger.info('break'); + if (!file.fileContents.includes('@locale')) { + return acc; } file.ast.walk(createVisitor({ EnumStatement: (enumStatement) => { From 800f1e51e0740ed35a4e37fae4d3e0814051e11f Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Thu, 18 Jul 2024 20:25:06 -0400 Subject: [PATCH 08/25] http client --- playlet-lib/src/source/services/HttpClient.bs | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/playlet-lib/src/source/services/HttpClient.bs b/playlet-lib/src/source/services/HttpClient.bs index f5f733454..c0b779cbc 100644 --- a/playlet-lib/src/source/services/HttpClient.bs +++ b/playlet-lib/src/source/services/HttpClient.bs @@ -1,10 +1,3 @@ -' DISABLE_CACHE will disable all caching for all requests. -' Only use this for debugging purposes. -#const DISABLE_CACHE = false -' NETWORK_THROTTLE will add a random delay to all requests to simulate network latency. -' Only use this for debugging purposes. -#const NETWORK_THROTTLE = false - import "pkg:/source/utils/CryptoUtils.bs" import "pkg:/source/utils/ErrorUtils.bs" import "pkg:/source/utils/Locale.bs" @@ -13,6 +6,13 @@ import "pkg:/source/utils/StringUtils.bs" import "pkg:/source/utils/Types.bs" import "pkg:/source/utils/UrlUtils.bs" +' DISABLE_CACHE will disable all caching for all requests. +' Only use this for debugging purposes. +#const DISABLE_CACHE = false +' NETWORK_THROTTLE will add a random delay to all requests to simulate network latency. +' Only use this for debugging purposes. +#const NETWORK_THROTTLE = false + namespace HttpClient const COMPRESSION_ENABLED = true @@ -121,7 +121,29 @@ namespace HttpClient class HttpRequest - public urlTransfer as object + public urlTransfer as roUrlTransfer + + public _cache as object + public _noCache as boolean + public _sent as boolean + public _cacheLocation as string + public _expireSeconds as integer + public _method as string + public _headers as roAssociativeArray + public _fileSystem as roFileSystem + + private _timeoutSeconds as integer + private _tryCount as integer + private _url as string + private _queryParams as roAssociativeArray + private _pathParams as roAssociativeArray + private _body as string + private _retryCallback as function + private _useHttp2 as boolean + private _cancellation as object + private _timer as roTimeSpan + private _cancelled as boolean + private _fullUrl as string function new() m._timeoutSeconds = 30 @@ -568,9 +590,15 @@ namespace HttpClient class HttpResponse public request as HttpRequest - public event as object + public event as roUrlEvent + + private _statusCode as integer + private _text as string + private _json as object + private _headers as object + private _errorMessage as string - function new(request as HttpRequest, event as object) + function new(request as HttpRequest, event as roUrlEvent) m.request = request m.event = event end function From aa00eca63b76baf7460f75e8c8687679b7c131fc Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Fri, 19 Jul 2024 09:47:15 -0400 Subject: [PATCH 09/25] qrcode --- playlet-lib/src/source/AsyncTask/AsyncTask.bs | 6 ++- playlet-lib/src/source/QrCode/QRBitBuffer.bs | 4 ++ playlet-lib/src/source/QrCode/QRCode.bs | 28 +++++++++--- .../src/source/QrCode/QRCode.exports.bs | 42 ------------------ .../src/source/QrCode/QRData_AlphaNumeric.bs | 7 ++- playlet-lib/src/source/QrCode/QRData_Byte.bs | 6 ++- .../src/source/QrCode/QRData_Numeric.bs | 8 +++- .../src/source/QrCode/QRMaskFunctions.bs | 43 +++++++++++++++++++ playlet-lib/src/source/QrCode/QRMath.bs | 2 + playlet-lib/src/source/QrCode/QRPolynomial.bs | 4 ++ playlet-lib/src/source/QrCode/QRRSBlock.bs | 3 ++ playlet-lib/src/source/QrCode/QRUtil.bs | 42 +++++++++++------- playlet-lib/src/source/QrCode/QrImage.bs | 12 +++--- 13 files changed, 134 insertions(+), 73 deletions(-) create mode 100644 playlet-lib/src/source/QrCode/QRMaskFunctions.bs diff --git a/playlet-lib/src/source/AsyncTask/AsyncTask.bs b/playlet-lib/src/source/AsyncTask/AsyncTask.bs index dd8d48fdf..92ee59364 100644 --- a/playlet-lib/src/source/AsyncTask/AsyncTask.bs +++ b/playlet-lib/src/source/AsyncTask/AsyncTask.bs @@ -2,6 +2,10 @@ import "pkg:/source/utils/Types.bs" namespace AsyncTask + interface AsyncTaskComponent extends roSGNodeTask + input as object + end interface + function Start(taskName as string, input as object, callback = invalid as object) as object task = Create(taskName, input, callback) task.control = "RUN" @@ -10,7 +14,7 @@ namespace AsyncTask function Create(taskName as string, input as object, callback = invalid as object) as object id = StrI(rnd(2147483647), 36) - task = createObject("roSGNode", taskName) + task = createObject("roSGNode", taskName) as AsyncTask.AsyncTaskComponent task.id = id task.input = input diff --git a/playlet-lib/src/source/QrCode/QRBitBuffer.bs b/playlet-lib/src/source/QrCode/QRBitBuffer.bs index 438b8de24..0bc4f4d7a 100644 --- a/playlet-lib/src/source/QrCode/QRBitBuffer.bs +++ b/playlet-lib/src/source/QrCode/QRBitBuffer.bs @@ -1,5 +1,9 @@ namespace QrCode class QRBitBuffer + + private buffer as roArray + private numberOfBits as integer + function new() m.buffer = [] m.numberOfBits = 0 diff --git a/playlet-lib/src/source/QrCode/QRCode.bs b/playlet-lib/src/source/QrCode/QRCode.bs index fa92afe08..6b7527d95 100644 --- a/playlet-lib/src/source/QrCode/QRCode.bs +++ b/playlet-lib/src/source/QrCode/QRCode.bs @@ -13,6 +13,24 @@ namespace QrCode class QRCode + private PAD0 as integer + private PAD1 as integer + + private dataNodes as roArray + private dataBytes as roArray + + private modules as roArray + private moduleCount as integer + + private typeNumber as integer + private errorCorrectionLevel as string + + private math as QRMath + private util as QRUtil + private rsBlock as QRRSBlock + + public status as string + function new() m.PAD0 = &HEC m.PAD1 = &H11 @@ -378,15 +396,15 @@ namespace QrCode end for end function - public function addData(data as string, qrType = QrCode.QrMode.Byte as QrCode.QrMode) as boolean + public function addData(data as string, qrType = QrMode.Byte as QrMode) as boolean - if qrType = QrCode.QrMode.AlphaNumeric + if qrType = QrMode.AlphaNumeric qrData = new QRData_Alphanumeric() - else if qrType = QrCode.QrMode.Numeric + else if qrType = QrMode.Numeric qrData = new QRData_Numeric() - else if qrType = QrCode.QrMode.Byte + else if qrType = QrMode.Byte qrData = new QRData_Byte() - else if qrType = QrCode.QrMode.Kanji + else if qrType = QrMode.Kanji ' NOTE: Kanji not supported - removed because it increases the code size significantly. ' Currently there's no use case for it, since we're mostly doing a QRCode for a url. ' If we need to support Kanji, we'll add it back. diff --git a/playlet-lib/src/source/QrCode/QRCode.exports.bs b/playlet-lib/src/source/QrCode/QRCode.exports.bs index 4fbf659b7..7d84e480b 100644 --- a/playlet-lib/src/source/QrCode/QRCode.exports.bs +++ b/playlet-lib/src/source/QrCode/QRCode.exports.bs @@ -24,46 +24,4 @@ namespace QrCode } end function - function QRMaskFunctions() as object - result = {} - - result.PATTERN000 = function(i as dynamic, j as dynamic) as boolean - return (i + j) mod 2 = 0 - end function - - result.PATTERN001 = function(i as dynamic, _j as dynamic) as boolean - return i mod 2 = 0 - end function - - result.PATTERN010 = function(_i as dynamic, j as dynamic) as boolean - return j mod 3 = 0 - end function - - result.PATTERN011 = function(i as dynamic, j as dynamic) as boolean - return (i + j) mod 3 = 0 - end function - - result.PATTERN100 = function(i as dynamic, j as dynamic) as boolean - return ((i \ 2) + (j \ 3)) mod 2 = 0 - end function - - result.PATTERN101 = function(i as dynamic, j as dynamic) as boolean - return ((i * j) mod 2) + ((i * j) mod 3) = 0 - end function - - result.PATTERN110 = function(i as dynamic, j as dynamic) as boolean - return (((i * j) mod 2) + ((i * j) mod 3)) mod 2 = 0 - end function - - result.PATTERN111 = function(i as dynamic, j as dynamic) as boolean - return (((i * j) mod 3) + ((i + j) mod 2)) mod 2 = 0 - end function - - return result - end function - - function QRMaskPatterns() as object - return QRMaskFunctions().keys() - end function - end namespace diff --git a/playlet-lib/src/source/QrCode/QRData_AlphaNumeric.bs b/playlet-lib/src/source/QrCode/QRData_AlphaNumeric.bs index 8a9c8ed3a..cf8c82a00 100644 --- a/playlet-lib/src/source/QrCode/QRData_AlphaNumeric.bs +++ b/playlet-lib/src/source/QrCode/QRData_AlphaNumeric.bs @@ -2,8 +2,13 @@ namespace QrCode class QRData_AlphaNumeric + private mode as integer + private data as string + private length as integer + private CHAR_TABLE as roAssociativeArray + function new() - m.mode = QrCode.QRMode.AlphaNumeric + m.mode = QRMode.AlphaNumeric m.CHAR_TABLE = { "0": 0 diff --git a/playlet-lib/src/source/QrCode/QRData_Byte.bs b/playlet-lib/src/source/QrCode/QRData_Byte.bs index 5ebd7984e..419e9ec4f 100644 --- a/playlet-lib/src/source/QrCode/QRData_Byte.bs +++ b/playlet-lib/src/source/QrCode/QRData_Byte.bs @@ -2,8 +2,12 @@ namespace QrCode class QRData_Byte + private mode as QRMode + private bytes as roByteArray + private length as integer + function new() - m.mode = QrCode.QRMode.Byte + m.mode = QRMode.Byte end function public function setData(data as string) diff --git a/playlet-lib/src/source/QrCode/QRData_Numeric.bs b/playlet-lib/src/source/QrCode/QRData_Numeric.bs index 4baa4ef76..d383eb720 100644 --- a/playlet-lib/src/source/QrCode/QRData_Numeric.bs +++ b/playlet-lib/src/source/QrCode/QRData_Numeric.bs @@ -2,8 +2,14 @@ namespace QrCode class QRData_Numeric + private mode as QRMode + private data as string + private length as integer + + private CHAR_TABLE as roAssociativeArray + function new() - m.mode = QrCode.QRMode.Numeric + m.mode = QRMode.Numeric m.CHAR_TABLE = { "0": 0 diff --git a/playlet-lib/src/source/QrCode/QRMaskFunctions.bs b/playlet-lib/src/source/QrCode/QRMaskFunctions.bs new file mode 100644 index 000000000..d088a6163 --- /dev/null +++ b/playlet-lib/src/source/QrCode/QRMaskFunctions.bs @@ -0,0 +1,43 @@ +namespace QrCode + + function QRMaskPatterns() as string[] + return ["PATTERN000", "PATTERN001", "PATTERN010", "PATTERN011", "PATTERN100", "PATTERN101", "PATTERN110", "PATTERN111"] + end function + + class QRMaskFunctions + + function PATTERN000(i as dynamic, j as dynamic) as boolean + return (i + j) mod 2 = 0 + end function + + function PATTERN001(i as dynamic, _j as dynamic) as boolean + return i mod 2 = 0 + end function + + function PATTERN010(_i as dynamic, j as dynamic) as boolean + return j mod 3 = 0 + end function + + function PATTERN011(i as dynamic, j as dynamic) as boolean + return (i + j) mod 3 = 0 + end function + + function PATTERN100(i as dynamic, j as dynamic) as boolean + return ((i \ 2) + (j \ 3)) mod 2 = 0 + end function + + function PATTERN101(i as dynamic, j as dynamic) as boolean + return ((i * j) mod 2) + ((i * j) mod 3) = 0 + end function + + function PATTERN110(i as dynamic, j as dynamic) as boolean + return (((i * j) mod 2) + ((i * j) mod 3)) mod 2 = 0 + end function + + function PATTERN111(i as dynamic, j as dynamic) as boolean + return (((i * j) mod 3) + ((i + j) mod 2)) mod 2 = 0 + end function + + end class + +end namespace diff --git a/playlet-lib/src/source/QrCode/QRMath.bs b/playlet-lib/src/source/QrCode/QRMath.bs index 8b94294d2..53270949a 100644 --- a/playlet-lib/src/source/QrCode/QRMath.bs +++ b/playlet-lib/src/source/QrCode/QRMath.bs @@ -1,6 +1,8 @@ namespace QrCode class QRMath + private EXP_TABLE as roArray + private LOG_TABLE as roArray function new() EXP_TABLE = createObject("roArray", 256, false) diff --git a/playlet-lib/src/source/QrCode/QRPolynomial.bs b/playlet-lib/src/source/QrCode/QRPolynomial.bs index 74bf1b6c3..b442a4374 100644 --- a/playlet-lib/src/source/QrCode/QRPolynomial.bs +++ b/playlet-lib/src/source/QrCode/QRPolynomial.bs @@ -1,6 +1,10 @@ namespace QrCode class QRPolynomial + + private math as QRMath + private _num as roArray + function new(math as QRMath, num as object, shift as integer) if type(num) <> "roArray" throw `Invalid num ${num}/${shift}` diff --git a/playlet-lib/src/source/QrCode/QRRSBlock.bs b/playlet-lib/src/source/QrCode/QRRSBlock.bs index ec715b58d..9bed1fc36 100644 --- a/playlet-lib/src/source/QrCode/QRRSBlock.bs +++ b/playlet-lib/src/source/QrCode/QRRSBlock.bs @@ -2,6 +2,9 @@ namespace QrCode class QRRSBlock + private ERROR_CORRECTION_LEVEL_OFFSETS as roAssociativeArray + private RS_BLOCK_TABLE as roArray + function new() m.ERROR_CORRECTION_LEVEL_OFFSETS = { L: 0 diff --git a/playlet-lib/src/source/QrCode/QRUtil.bs b/playlet-lib/src/source/QrCode/QRUtil.bs index e13a88be9..0da3de80c 100644 --- a/playlet-lib/src/source/QrCode/QRUtil.bs +++ b/playlet-lib/src/source/QrCode/QRUtil.bs @@ -1,7 +1,18 @@ +import "QRMaskFunctions.bs" + namespace QrCode class QRUtil + private math as QRMath + private PATTERN_POSITION_TABLE as roArray + + private G15 as integer + private G18 as integer + private G15_MASK as integer + private G15_BCHDigit as integer + private G18_BCHDigit as integer + function new(math as QRMath) m.math = math m.PATTERN_POSITION_TABLE = [ @@ -53,7 +64,6 @@ namespace QrCode m.G15_BCHDigit = m.getBCHDigit(m.G15) m.G18_BCHDigit = m.getBCHDigit(m.G18) - end function function getBCHDigit(data as integer) as integer @@ -87,21 +97,21 @@ namespace QrCode end function function getMaskFunction(maskPattern as integer) as function - masks = QRMaskFunctions() + masks = new QRMaskFunctions() patterns = QRMaskPatterns() maskId = patterns[maskPattern] if maskId = invalid or masks[maskId] = invalid - ' print "Invalid maskPattern", maskPattern - return function(_i as dynamic, _j as dynamic) as boolean - ' print "Invalid maskPattern used" - return false - end function + return m.InvalidMaskFunction end if return masks[maskId] end function + function InvalidMaskFunction(_i as dynamic, _j as dynamic) as boolean + return false + end function + function getErrorCorrectPolynomial(errorCorrectLength as integer) as object a = new QRPolynomial(m.math, [1], 0) for i = 0 to errorCorrectLength - 1 step 1 @@ -113,35 +123,35 @@ namespace QrCode function getLengthInBits(mode as integer, typeNumber as integer) as integer if 1 <= typeNumber and typeNumber < 10 ' 1 - 9 - if mode = QrCode.QrMode.Numeric + if mode = QrMode.Numeric return 10 end if - if mode = QrCode.QrMode.AlphaNumeric + if mode = QrMode.AlphaNumeric return 9 end if - if mode = QrCode.QrMode.Byte + if mode = QrMode.Byte return 8 end if else if typeNumber < 27 ' 10 - 26 - if mode = QrCode.QrMode.Numeric + if mode = QrMode.Numeric return 12 end if - if mode = QrCode.QrMode.AlphaNumeric + if mode = QrMode.AlphaNumeric return 11 end if - if mode = QrCode.QrMode.Byte + if mode = QrMode.Byte return 16 end if else if typeNumber < 41 ' 27 - 40 - if mode = QrCode.QrMode.Numeric + if mode = QrMode.Numeric return 14 end if - if mode = QrCode.QrMode.AlphaNumeric + if mode = QrMode.AlphaNumeric return 13 end if - if mode = QrCode.QrMode.Byte + if mode = QrMode.Byte return 16 end if end if diff --git a/playlet-lib/src/source/QrCode/QrImage.bs b/playlet-lib/src/source/QrCode/QrImage.bs index 83960be56..69ff3b88f 100644 --- a/playlet-lib/src/source/QrCode/QrImage.bs +++ b/playlet-lib/src/source/QrCode/QrImage.bs @@ -1,14 +1,14 @@ +import "pkg:/source/utils/CryptoUtils.bs" +import "QRCode.bs" + ' DISABLE_CACHE will force the generation of the QRCode every time. ' Only use this for debugging purposes. #const DISABLE_CACHE = false -import "pkg:/source/utils/CryptoUtils.bs" -import "QRCode.bs" - namespace QrCode class QRImage - function Generate(text as string, size as integer, padding as integer, mode = QrCode.QrMode.Byte as QrCode.QrMode) as string + function Generate(text as string, size as integer, padding as integer, mode = QrMode.Byte as QrMode) as string fileName = m.GetFileName(text, mode, size, padding) #if DEBUG @@ -22,7 +22,7 @@ namespace QrCode #end if #end if - qr = new QrCode.QRCode() + qr = new QRCode() qr.addData(text, mode) qr.make() @@ -33,7 +33,7 @@ namespace QrCode return "" end function - function GetFileName(text as string, mode as QrCode.QrMode, size as integer, padding as integer) as string + function GetFileName(text as string, mode as QrMode, size as integer, padding as integer) as string key = `v1-${text}-${mode}-${size}-${padding}` key = CryptoUtils.GetMd5(key) return "cachefs:/" + key + ".png" From 84033f361ed5089fff0faba7eab7373aed212277 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Fri, 19 Jul 2024 12:32:49 -0400 Subject: [PATCH 10/25] app info --- .../Services/ApplicationInfo/ApplicationInfo.bs | 14 ++++++++------ .../src/source/services/ApplicationInfo.bs | 16 +++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs index f7c7235ab..1f9c2185d 100644 --- a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs +++ b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs @@ -31,12 +31,14 @@ function GetLatestPlayletLibVersion(_unused as dynamic) as dynamic return invalid end if - m.latestLibVersionTask = AsyncTask.Start(Tasks.LatestLibVersionTask, {}, function(output as object) as void - m.latestLibVersionTask = invalid - if output.success and output.result.latest <> invalid - m.top.lib_version_latest = output.result.latest - end if - end function) + m.latestLibVersionTask = AsyncTask.Start(Tasks.LatestLibVersionTask, {}, OnLatestLibVersionTaskResult) return invalid end function + +function OnLatestLibVersionTaskResult(output as object) as void + m.latestLibVersionTask = invalid + if output.success and output.result.latest <> invalid + m.top.lib_version_latest = output.result.latest + end if +end function diff --git a/playlet-lib/src/source/services/ApplicationInfo.bs b/playlet-lib/src/source/services/ApplicationInfo.bs index 846257cd0..565478cda 100644 --- a/playlet-lib/src/source/services/ApplicationInfo.bs +++ b/playlet-lib/src/source/services/ApplicationInfo.bs @@ -1,9 +1,15 @@ import "pkg:/source/utils/StringUtils.bs" class ApplicationInfo - public node as object - public roDeviceInfo as object - public roAppInfo as object + public node as roSGNodeApplicationInfo + public roDeviceInfo as roDeviceInfo + public roAppInfo as roAppInfo + + private ipAddress as string + private countryCode as string + private appInfo as roAssociativeArray + private deviceInfo as roAssociativeArray + private libManifestValues as roAssociativeArray function new(node as object) m.node = node @@ -29,7 +35,7 @@ class ApplicationInfo return m.countryCode end function - function GetAppInfo() as object + function GetAppInfo() as roAssociativeArray if m.appInfo = invalid m.appInfo = { id: m.roAppInfo.GetID() @@ -61,7 +67,7 @@ class ApplicationInfo return m.appInfo end function - function GetDeviceInfo() as object + function GetDeviceInfo() as roAssociativeArray if m.deviceInfo = invalid m.deviceInfo = { model: m.roDeviceInfo.GetModel() From 0a81ece4afb28f57d03e24c0c1bbc22b77e9f776 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Fri, 19 Jul 2024 13:18:34 -0400 Subject: [PATCH 11/25] tracking plugin --- tools/bs-plugins/track-transpiled-plugin.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/bs-plugins/track-transpiled-plugin.ts b/tools/bs-plugins/track-transpiled-plugin.ts index f9f63483b..a55e23c7f 100644 --- a/tools/bs-plugins/track-transpiled-plugin.ts +++ b/tools/bs-plugins/track-transpiled-plugin.ts @@ -11,7 +11,8 @@ // Can be caught by inspecting the diff in the transpiled files. import { - CompilerPlugin, FileObj, ProgramBuilder, + AfterBuildProgramEvent, + CompilerPlugin, } from 'brighterscript'; import { globSync } from "glob"; import path from 'path'; @@ -20,14 +21,14 @@ import fs from 'fs-extra' export class TrackTranspiledPlugin implements CompilerPlugin { public name = 'TrackTranspiledPlugin'; - afterPublish(builder: ProgramBuilder, files: FileObj[]) { + afterBuildProgram(event: AfterBuildProgramEvent) { // @ts-ignore - if (!builder.options.testMode) { + if (!event.program.options.testMode) { return; } - const stagingDir = builder.options.stagingDir!; - const rootDir = builder.rootDir; + const stagingDir = event.program.options.stagingDir!; + const rootDir = event.program.options.rootDir!; const transpiledFolders = globSync('**/*.transpiled', { cwd: rootDir }); for (let i = 0; i < transpiledFolders.length; i++) { From aa4a140fbe31d9acb1b93826cad092cd882d756f Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Fri, 19 Jul 2024 14:25:46 -0400 Subject: [PATCH 12/25] logger plugin --- tools/bs-plugins/logger-plugin.ts | 103 +++++++++++++++--------------- 1 file changed, 51 insertions(+), 52 deletions(-) diff --git a/tools/bs-plugins/logger-plugin.ts b/tools/bs-plugins/logger-plugin.ts index 54cd79434..749e5298c 100644 --- a/tools/bs-plugins/logger-plugin.ts +++ b/tools/bs-plugins/logger-plugin.ts @@ -1,15 +1,18 @@ // This plugin generates logging functions based on the usage of the LogError, LogWarn, LogInfo, and LogDebug functions. import { - AstEditor, - BeforeFileTranspileEvent, - BscFile, + BeforeBuildProgramEvent, + BeforePrepareFileEvent, + BrsFile, + CallExpression, CompilerPlugin, + DottedGetExpression, + ParseMode, Program, SourceLiteralExpression, TokenKind, - TranspileObj, WalkMode, + createIdentifier, createToken, createVisitor, isBrsFile, @@ -48,48 +51,43 @@ export class LoggerPlugin implements CompilerPlugin { private hasLogger = false; - beforeProgramTranspile(program: Program, entries: TranspileObj[], editor: AstEditor) { - this.hasLogger = program.hasFile(loggingFilePath); + beforeBuildProgram(event: BeforeBuildProgramEvent) { + this.hasLogger = event.program.hasFile(loggingFilePath); if (!this.hasLogger) { return; } const usedLogFunctions = new Map(); + const visitor = createVisitor({ + ExpressionStatement: (statement) => { + const expression = statement.expression as CallExpression; + const callee = expression.callee as DottedGetExpression; + const funcName = callee.getName(ParseMode.BrightScript); + if (funcName && logFunctionKeys.includes(funcName)) { + const argCount = expression.args.length + 1; // +1 for the file path + const newFuncName = `${funcName}${argCount}`; + usedLogFunctions.set(newFuncName, { + name: funcName, + argCount: argCount, + }); + } + }, + }); - for (const entry of entries) { - if (!isBrsFile(entry.file)) { + for (const file of event.files) { + if (!isBrsFile(file)) { continue; } - const visitor = createVisitor({ - ExpressionStatement: (statement) => { - // @ts-ignore - const funcName = statement.expression.callee?.name?.text; - if (funcName && logFunctionKeys.includes(funcName)) { - // @ts-ignore - const argCount = statement.expression.args.length + 1; // +1 for the file path - const newFuncName = `${funcName}${argCount}`; - usedLogFunctions.set(newFuncName, { - name: funcName, - argCount: argCount, - }); - } - }, + file.ast.walk(visitor, { + walkMode: WalkMode.visitStatementsRecursive }); - - for (const func of entry.file.parser.references.functionExpressions) { - func.body.walk(visitor, { - walkMode: WalkMode.visitStatements - }); - } } - // @ts-ignore - const isDebug = !!program.options.debug; - this.generateLoggingFile(program, usedLogFunctions, isDebug); + this.generateLoggingFile(event.program, usedLogFunctions); } - beforeFileTranspile(event: BeforeFileTranspileEvent) { + beforePrepareFile(event: BeforePrepareFileEvent) { if (!this.hasLogger) { return; } @@ -103,40 +101,41 @@ export class LoggerPlugin implements CompilerPlugin { const visitor = createVisitor({ ExpressionStatement: (statement) => { - // @ts-ignore - const funcName = statement.expression.callee?.name?.text; + const expression = statement.expression as CallExpression; + const callee = expression.callee as DottedGetExpression; + const funcName = callee.getName(ParseMode.BrightScript); if (funcName && logFunctionKeys.includes(funcName)) { - // @ts-ignore - const args = statement.expression.args; + const args = expression.args; if (isDebug) { - const t = createToken(TokenKind.SourceLocationLiteral, '', statement.expression.range); - let sourceExpression = new SourceLiteralExpression(t); + const t = createToken(TokenKind.SourceLocationLiteral, '', statement.expression.location); + const sourceExpression = new SourceLiteralExpression({ value: t }); event.editor.addToArray(args, 0, sourceExpression); } else { - const fileName = path.basename(event.file.pkgPath); - const line = statement.range!.start.line; - const t = createToken(TokenKind.StringLiteral, `\"[${fileName}:${line}]\"`, statement.expression.range); - let sourceExpression = new SourceLiteralExpression(t); + const fileName = path.basename(event.file.srcPath); + const line = statement.location!.range.start.line + 1; // range.start.line is 0-based + const t = createToken(TokenKind.StringLiteral, `\"[${fileName}:${line}]\"`, statement.expression.location); + const sourceExpression = new SourceLiteralExpression({ value: t }); event.editor.addToArray(args, 0, sourceExpression); } const newFuncName = `${funcName}${args.length}`; + const newFuncIdentifier = createIdentifier(newFuncName, callee.location); event.program.logger.info(this.name, `Replacing ${funcName} with ${newFuncName}`); - // @ts-ignore - event.editor.setProperty(statement.expression.callee?.name, 'text', `${newFuncName}`) + event.editor.setProperty(callee.tokens, 'name', newFuncIdentifier); } }, }); - for (const func of event.file.parser.references.functionExpressions) { - func.body.walk(visitor, { - walkMode: WalkMode.visitStatements - }); - } + event.file.ast.walk(visitor, { + walkMode: WalkMode.visitStatementsRecursive + }); } - generateLoggingFile(program: Program, usedLogFunctions: Map, isDebug: boolean) { - const file = program.getFile(loggingFilePath); + generateLoggingFile(program: Program, usedLogFunctions: Map) { + // @ts-ignore + const isDebug = !!program.options.debug; + + const file = program.getFile(loggingFilePath) as BrsFile; let content = file.fileContents; content += '\n\' Start of auto-generated functions\n' @@ -145,7 +144,7 @@ export class LoggerPlugin implements CompilerPlugin { }); content += '\n\' End of auto-generated functions\n' - program.setFile(loggingFilePath, content) + file.parse(content); } generateLoggingFunction(newFunctionName: string, level: string, argCount: number, isDebug: boolean) { From c3ec9c296443ea25ea61bde6ce681692dffedd23 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Fri, 19 Jul 2024 14:36:25 -0400 Subject: [PATCH 13/25] app info types --- .../Services/ApplicationInfo/ApplicationInfo.bs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs index 1f9c2185d..e49b2a192 100644 --- a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs +++ b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs @@ -2,15 +2,23 @@ import "pkg:/source/AsyncTask/AsyncTask.bs" import "pkg:/source/AsyncTask/Tasks.bs" import "pkg:/source/services/ApplicationInfo.bs" +typecast m as ApplicationInfoRoSGNode + +interface ApplicationInfoRoSGNode + top as roSgNodeApplicationInfo + service as ApplicationInfo + latestLibVersionTask as AsyncTask.AsyncTaskComponent +end interface + function Init() m.service = new ApplicationInfo(m.top) end function -function GetAppInfo(_unused as dynamic) as object +function GetAppInfo(_unused as dynamic) as roAssociativeArray return m.service.GetAppInfo() end function -function GetDeviceInfo(_unused as dynamic) as object +function GetDeviceInfo(_unused as dynamic) as roAssociativeArray return m.service.GetDeviceInfo() end function From 26437ae10a041c7141f7b19c6cf29baab8b014ee Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Fri, 19 Jul 2024 15:20:46 -0400 Subject: [PATCH 14/25] oninit plugin --- tools/bs-plugins/Classes/RawCodeStatement.ts | 8 ++- tools/bs-plugins/oninit-plugin.ts | 66 +++++++++++++------- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/tools/bs-plugins/Classes/RawCodeStatement.ts b/tools/bs-plugins/Classes/RawCodeStatement.ts index 4f3052e25..9890a00da 100644 --- a/tools/bs-plugins/Classes/RawCodeStatement.ts +++ b/tools/bs-plugins/Classes/RawCodeStatement.ts @@ -5,8 +5,9 @@ import type { WalkVisitor } from 'brighterscript'; import { + AstNodeKind, Range, - Statement + Statement, } from 'brighterscript'; import { SourceNode } from 'source-map'; @@ -22,6 +23,9 @@ export class RawCodeStatement extends Statement { super(); } + public readonly kind = AstNodeKind.ExpressionStatement; + public readonly location: undefined; + public transpile(state: BrsTranspileState) { //indent every line with the current transpile indent level (except the first line, because that's pre-indented by bsc) let source = this.source.replace(/\r?\n/g, (match, newline) => { @@ -31,7 +35,7 @@ export class RawCodeStatement extends Statement { return [new SourceNode( this.range.start.line + 1, this.range.start.character, - this.sourceFile ? this.sourceFile.pathAbsolute : state.srcPath, + this.sourceFile ? this.sourceFile.srcPath : state.srcPath, source )]; } diff --git a/tools/bs-plugins/oninit-plugin.ts b/tools/bs-plugins/oninit-plugin.ts index 56a567a94..c38edae30 100644 --- a/tools/bs-plugins/oninit-plugin.ts +++ b/tools/bs-plugins/oninit-plugin.ts @@ -1,16 +1,16 @@ // This plugin takes functions annotated with @oninit and adds them to the component's Init function import { + AfterFileValidateEvent, AnnotationExpression, - BeforeFileTranspileEvent, + BeforePrepareFileEvent, + BeforeScopeValidateEvent, BrsFile, - BscFile, Callable, - CallableContainerMap, CompilerPlugin, DiagnosticSeverity, FunctionStatement, - Scope, + ParseMode, XmlScope, isBrsFile, isXmlScope, @@ -28,7 +28,8 @@ import { RawCodeStatement } from './Classes/RawCodeStatement'; export class OnInitPlugin implements CompilerPlugin { public name = 'OnInitPlugin'; - afterScopeValidate(scope: Scope, files: BscFile[], callables: CallableContainerMap) { + afterScopeValidate(event: BeforeScopeValidateEvent) { + const scope = event.scope; if (!isXmlScope(scope)) { return; } @@ -38,21 +39,25 @@ export class OnInitPlugin implements CompilerPlugin { return; } + const program = event.program; + program.diagnostics.clearByFilter({ file: scope.xmlFile, tag: this.name }); + const initFunction = this.getInitCallableInScope(scope); if (!initFunction) { onInitCallables.forEach((onInitCallable) => { - scope.xmlFile.addDiagnostics([{ + program.diagnostics.register({ file: scope.xmlFile, - range: onInitCallable.annotation!.range, - message: `function ${onInitCallable.callable.functionStatement.name.text} with @oninit annotation is included in ${scope.name}, but no Init function was found in the component.`, + range: onInitCallable.annotation!.location!.range, + message: `function ${onInitCallable.callable.functionStatement.getName(ParseMode.BrightScript)} with @oninit annotation is included in ${scope.name}, but no Init function was found in the component.`, severity: DiagnosticSeverity.Error, - code: 1818 - }]); + code: "ONINIT_NO_INIT_FUNCTION" + }); }); } } - afterFileValidate(file: BscFile) { + afterFileValidate(event: AfterFileValidateEvent) { + const file = event.file; if (!isBrsFile(file)) { return } @@ -71,34 +76,47 @@ export class OnInitPlugin implements CompilerPlugin { return; } + program.diagnostics.clearByFilter({ file: file, tag: this.name }); + const initFunction = this.getInitCallableInFile(file); if (initFunction && scopes.length > 1 && onInitCallables.length > 0) { - file.addDiagnostics([{ + program.diagnostics.register({ file, - range: initFunction.functionStatement!.func.range, + range: initFunction.functionStatement.location!.range, message: `Init function will call @oninit functions, but is included in multiple scopes.`, severity: DiagnosticSeverity.Error, - code: 1819 - }]); + code: "ONINIT_INIT_FUNCTION_MULTIPLE_SCOPES" + }); } for (let i = 0; i < onInitCallables.length; i++) { const onInitCallable = onInitCallables[i]; - const functionName = onInitCallable.callable.functionStatement?.name.text; + const functionName = onInitCallable.callable.functionStatement.getName(ParseMode.BrightScript); if (!functionName) { - file.addDiagnostics([{ + program.diagnostics.register({ file: onInitCallable.callable.file, - range: onInitCallable.annotation!.range, + range: onInitCallable.annotation!.location!.range, message: `function with @oninit annotation must have a name`, severity: DiagnosticSeverity.Error, - code: 1820 - }]); + code: "ONINIT_FUNCTION_NO_NAME" + }); + } + + const paramCount = onInitCallable.callable.functionStatement.func.parameters.length; + if (paramCount > 0) { + program.diagnostics.register({ + file: onInitCallable.callable.file, + range: onInitCallable.annotation!.location!.range, + message: `function ${functionName} with @oninit annotation must not have parameters`, + severity: DiagnosticSeverity.Error, + code: "ONINIT_FUNCTION_PARAMETERS" + }); } } } - beforeFileTranspile(event: BeforeFileTranspileEvent) { + beforePrepareFile(event: BeforePrepareFileEvent) { if (!isBrsFile(event.file)) { return } @@ -138,7 +156,7 @@ export class OnInitPlugin implements CompilerPlugin { for (let i = 0; i < onInitCallables.length; i++) { const onInitCallable = onInitCallables[i]; - const functionName = onInitCallable.callable.functionStatement?.name.text; + const functionName = onInitCallable.callable.functionStatement.getName(ParseMode.BrightScript); if (!functionName) { continue; } @@ -171,13 +189,13 @@ export class OnInitPlugin implements CompilerPlugin { getInitCallableInFile(file: BrsFile): Callable | undefined { return file.callables.find((callable) => { - return callable.functionStatement?.name.text === "Init"; + return callable.functionStatement.getName(ParseMode.BrightScript) === "Init"; }); } getInitCallableInScope(scope: XmlScope): Callable | undefined { return scope.getOwnCallables().find((callable) => { - return callable.callable.functionStatement?.name.text === "Init"; + return callable.callable.functionStatement.getName(ParseMode.BrightScript) === "Init"; })?.callable; } From 6e7171f27325ee205e865ee6e7a71388777261d3 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Sat, 20 Jul 2024 17:16:52 -0400 Subject: [PATCH 15/25] includes component --- tools/bs-plugins/component-includes-plugin.ts | 126 ++++++++++++------ 1 file changed, 86 insertions(+), 40 deletions(-) diff --git a/tools/bs-plugins/component-includes-plugin.ts b/tools/bs-plugins/component-includes-plugin.ts index 20009359c..0fb796b8a 100644 --- a/tools/bs-plugins/component-includes-plugin.ts +++ b/tools/bs-plugins/component-includes-plugin.ts @@ -1,15 +1,16 @@ // Plugin to allow including other components in a component import { - BscFile, + AfterProvideFileEvent, CompilerPlugin, DiagnosticSeverity, Program, XmlFile, + createSGScript, isXmlFile, util, } from 'brighterscript'; -import { SGChildren, SGComponent, SGInterface, SGScript } from 'brighterscript/dist/parser/SGTypes'; +import { SGChildren, SGComponent } from 'brighterscript/dist/parser/SGTypes'; import { globSync } from 'glob'; import fs from 'fs-extra' import path from 'path'; @@ -17,53 +18,67 @@ import path from 'path'; export class ComponentIncludesPlugin implements CompilerPlugin { public name = 'ComponentIncludesPlugin'; - afterFileParse(file: BscFile) { + afterProvideFile(event: AfterProvideFileEvent) { + if (event.files.length !== 1) { + return; + } + + const file = event.files[0]; if (!isXmlFile(file)) { return; } const program = file.program; - const component = file.parser.ast.component; + const component = file.parser.ast.componentElement; if (!component) { return; } + const includes = this.getIncludes(component); if (includes.length === 0) { return; } + program.diagnostics.clearByFilter({ file: file, tag: this.name }); + includes.forEach((include) => { const rootDir = program.options.rootDir!; const includePaths = globSync(`**/${include.name}.part.xml`, { cwd: rootDir }); if (includePaths.length === 0) { - file.addDiagnostics([{ + program.diagnostics.register({ file: file, range: include.range!, message: `Could not find include: ${include.name}`, severity: DiagnosticSeverity.Error, code: 'INCLUDE_NOT_FOUND', - }]); + }, { tags: [this.name] }); return; } + if (includePaths.length > 1) { - file.addDiagnostics([{ + program.diagnostics.register({ file: file, range: include.range!, - message: `Found multiple include files for include: ${include}`, + message: `Found multiple include files for include: ${include.name}`, severity: DiagnosticSeverity.Error, code: 'MULTIPLE_INCLUDES_FOUND', - }]); + }, { tags: [this.name] }); return; } const includePath = includePaths[0]; const srcPath = path.join(rootDir, includePath); - const xmlFile = new XmlFile(srcPath, includePath, program); + + const xmlFile = new XmlFile({ + srcPath: srcPath, + program: program, + destPath: includePath, + }); const includeFileContents = fs.readFileSync(srcPath, 'utf8'); xmlFile.parse(includeFileContents); - const includeComponent = xmlFile.ast.component; + const includeComponent = xmlFile.ast.componentElement; if (!includeComponent) { return; } @@ -74,15 +89,17 @@ export class ComponentIncludesPlugin implements CompilerPlugin { this.addChildren(component, includeComponent); }); - component.attributes = component.attributes.filter((attr) => { - return attr.key.text !== 'includes'; - }); - + component.removeAttribute('includes'); file.parser.invalidateReferences(); } addScripts(component: SGComponent, includeComponent: SGComponent, includePath: string, program: Program) { - component.scripts.push(...includeComponent.scripts); + const includeScripts = includeComponent.scriptElements; + for (let i = 0; i < includeScripts.length; i++) { + const script = includeScripts[i]; + component.addChild(script); + } + if (program.options.autoImportComponentScript) { const possibleCodeBehindPkgPaths = [ includePath.replace('.xml', '.bs'), @@ -91,68 +108,97 @@ export class ComponentIncludesPlugin implements CompilerPlugin { possibleCodeBehindPkgPaths.forEach((scriptPkgPath) => { const scriptFilePath = path.join(program.options.rootDir!, scriptPkgPath); if (fs.existsSync(scriptFilePath)) { - const scriptTag = new SGScript(); - scriptTag.type = "text/brightscript" - scriptTag.uri = util.getRokuPkgPath(scriptPkgPath); - - component.scripts.push(scriptTag); + const scriptTag = createSGScript({ + type: "text/brightscript", + uri: util.sanitizePkgPath(scriptPkgPath), + }) + component.addChild(scriptTag); } }); } } addFields(component: SGComponent, includeComponent: SGComponent) { - if (!includeComponent.api) { + const interfaceElement = includeComponent.interfaceElement; + if (!interfaceElement) { return; } - if (!includeComponent.api.fields || includeComponent.api.fields.length === 0) { + + const fields = interfaceElement.fields; + if (!fields || fields.length === 0) { return; } - if (!component.api) { - component.api = new SGInterface({ text: 'interface' }, []) + for (let i = 0; i < fields.length; i++) { + const field = fields[i]; + let alwaysNotify: boolean | undefined = undefined; + if (field.alwaysNotify) { + alwaysNotify = field.alwaysNotify === 'true'; + } + component.setInterfaceField(field.id, field.type, field.onChange, alwaysNotify, field.alias); } - component.api.fields.push(...includeComponent.api.fields); } addFunctions(component: SGComponent, includeComponent: SGComponent) { - if (!includeComponent.api) { + const interfaceElement = includeComponent.interfaceElement; + if (!interfaceElement) { return; } - if (!includeComponent.api.functions || includeComponent.api.functions.length === 0) { + + const functions = interfaceElement.functions; + if (!functions || functions.length === 0) { return; } - if (!component.api) { - component.api = new SGInterface({ text: 'interface' }, []) + + for (let i = 0; i < functions.length; i++) { + const func = functions[i]; + component.setInterfaceFunction(func.name); } - component.api.functions.push(...includeComponent.api.functions); } addChildren(component: SGComponent, includeComponent: SGComponent) { - if (!includeComponent.children) { + const includeChildren = includeComponent.childrenElement; + if (!includeChildren) { return; } - if (!includeComponent.children.children || includeComponent.children.children.length === 0) { + + if (includeChildren.elements.length === 0) { return; } - if (!component.children) { - component.children = new SGChildren({ text: 'children' }, []) + + let componentChildren = component.childrenElement; + if (!componentChildren) { + componentChildren = new SGChildren({ + startTagOpen: { text: '<' }, + startTagName: { text: 'children' }, + startTagClose: { text: '>' }, + elements: [], + endTagOpen: { text: '' } + }); + component.addChild(componentChildren); + } + for (let i = 0; i < includeChildren.elements.length; i++) { + const child = includeChildren.elements[i]; + componentChildren.elements.push(child); } - component.children.children.push(...includeComponent.children.children); } - getIncludes(component?: SGComponent) { if (!component || !component.attributes) { return []; } return component.attributes.filter((attr) => { - return attr.key.text === 'includes'; + return attr.key === 'includes'; }).map((attr) => { - return attr.value.text.split(',').map((item) => { + if (!attr.value) { + return []; + } + return attr.value.split(',').map((item) => { return { name: item.trim(), - range: attr.value.range, + range: attr.tokens.value?.location?.range, } }); }).flat(); From fb84290f835d7b805290af6f4c17e6ff77d7e035 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Sat, 20 Jul 2024 21:02:38 -0400 Subject: [PATCH 16/25] image gen --- tools/bs-plugins/image-gen-plugin.ts | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tools/bs-plugins/image-gen-plugin.ts b/tools/bs-plugins/image-gen-plugin.ts index 55e17ed99..2b967787a 100644 --- a/tools/bs-plugins/image-gen-plugin.ts +++ b/tools/bs-plugins/image-gen-plugin.ts @@ -1,7 +1,9 @@ // This plugin converts svg files to png/jpeg files import { - CompilerPlugin, FileObj, ProgramBuilder, + BeforeBuildProgramEvent, + BscFile, + CompilerPlugin, } from 'brighterscript'; import { readFileSync, writeFileSync } from 'fs'; import { existsSync } from 'fs-extra'; @@ -9,6 +11,7 @@ import { globSync } from 'glob'; import md5 from 'crypto-js/md5'; import { join as joinPath } from 'path'; import json5 from 'json5'; +import { AssetFile } from 'brighterscript/dist/files/AssetFile'; const shell = require('shelljs'); const META_EXT = '.meta.json5'; @@ -16,13 +19,13 @@ const META_EXT = '.meta.json5'; export class ImageGenPlugin implements CompilerPlugin { public name = 'ImageGenPlugin'; - beforePrepublish(builder: ProgramBuilder, files: FileObj[]) { - // Force generate flag + beforeBuildProgram(event: BeforeBuildProgramEvent) { + const options = event.program.options; // @ts-ignore - const forceGenerateImages = !!builder.options.forceGenerateImages; + const forceGenerateImages = !!options.forceGenerateImages; // Debug flag // @ts-ignore - const debug = !!builder.options.debug; + const debug = !!options.debug; if (debug && !forceGenerateImages) { // Since the plugin does a lot of scanning of files, it is fine not to run it in debug mode @@ -30,8 +33,7 @@ export class ImageGenPlugin implements CompilerPlugin { return; } - const rootDir = builder.options.rootDir!; - + const rootDir = options.rootDir!; const svgFiles = globSync(`**/*.svg`, { cwd: rootDir }); svgFiles.forEach((svgFile) => { @@ -47,7 +49,7 @@ export class ImageGenPlugin implements CompilerPlugin { const meta = json5.parse(readFileSync(metafile, 'utf8')); - this.generateImages(svgFile, meta, metafile, rootDir, files, forceGenerateImages); + this.generateImages(svgFile, meta, metafile, rootDir, event.files, forceGenerateImages); }); } @@ -65,7 +67,7 @@ export class ImageGenPlugin implements CompilerPlugin { writeFileSync(metafile, json5.stringify(meta, null, 2)); } - generateImages(svgFile: string, meta: any, metafile: string, rootDir: string, files: FileObj[], forceGenerateImages: boolean) { + generateImages(svgFile: string, meta: any, metafile: string, rootDir: string, files: BscFile[], forceGenerateImages: boolean) { let metaChanged = false; const inputHash = this.checkFileHash(joinPath(rootDir, svgFile), meta.inputHash); if (!inputHash.valid) { @@ -86,7 +88,13 @@ export class ImageGenPlugin implements CompilerPlugin { this.generateImage(svgFile, output, rootDir); outputHash = this.checkFileHash(outputFilePath, output.outputHash); - files.push({ src: outputFilePath, dest: output.outputFilePath }) + const file = new AssetFile({ + srcPath: outputFilePath, + destPath: outputFilePath.replace(rootDir, ''), + data: () => readFileSync(outputFilePath), + }); + + files.push(file) output.outputHash = outputHash.hash; metaChanged = true; From 2ffc66e23bbe3ced724968a11439883fd36885cc Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Sat, 20 Jul 2024 21:02:45 -0400 Subject: [PATCH 17/25] include plugin --- tools/bs-plugins/component-includes-plugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bs-plugins/component-includes-plugin.ts b/tools/bs-plugins/component-includes-plugin.ts index 0fb796b8a..8ba97e621 100644 --- a/tools/bs-plugins/component-includes-plugin.ts +++ b/tools/bs-plugins/component-includes-plugin.ts @@ -29,6 +29,8 @@ export class ComponentIncludesPlugin implements CompilerPlugin { } const program = file.program; + program.diagnostics.clearByFilter({ file: file, tag: this.name }); + const component = file.parser.ast.componentElement; if (!component) { return; @@ -39,8 +41,6 @@ export class ComponentIncludesPlugin implements CompilerPlugin { return; } - program.diagnostics.clearByFilter({ file: file, tag: this.name }); - includes.forEach((include) => { const rootDir = program.options.rootDir!; From 2d5a7109cade7f0bf21ac9f84371a40137e73b7f Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Mon, 22 Jul 2024 22:24:31 -0400 Subject: [PATCH 18/25] web plugin --- tools/bs-plugins/web-server-plugin.ts | 32 ++++++++++++++------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/tools/bs-plugins/web-server-plugin.ts b/tools/bs-plugins/web-server-plugin.ts index 8b3574b97..4b57e6145 100644 --- a/tools/bs-plugins/web-server-plugin.ts +++ b/tools/bs-plugins/web-server-plugin.ts @@ -2,15 +2,15 @@ // associated functions with the router. import { - BeforeFileTranspileEvent, - BscFile, + BeforePrepareFileEvent, ClassStatement, CompilerPlugin, + DiagnosticSeverity, FunctionExpression, FunctionStatement, MethodStatement, OnFileValidateEvent, - TokenKind, + ParseMode, WalkMode, createVisitor, isBrsFile @@ -23,11 +23,14 @@ const httpRouterBaseClass = 'HttpRouter'; export class WebServerPlugin implements CompilerPlugin { public name = 'WebServerPlugin'; - onFileValidate(event: OnFileValidateEvent) { + onFileValidate(event: OnFileValidateEvent) { if (!isBrsFile(event.file)) { return; } + const program = event.program; + program.diagnostics.clearByFilter({ file: event.file, tag: this.name }); + // Make sure each class that inherits from HttpRouter has a constructor event.file.ast.walk(createVisitor({ ClassStatement: (classStmt) => { @@ -35,20 +38,20 @@ export class WebServerPlugin implements CompilerPlugin { return; } - const parentClass = classStmt.parentClassName.expression.name.text; + const parentClass = classStmt.parentClassName.getName(); if (parentClass !== httpRouterBaseClass) { return; } const classConstructor = this.getClassConstructor(classStmt); if (!classConstructor) { - event.file.addDiagnostics([{ + program.diagnostics.register({ file: event.file, - range: classStmt.name.range, - message: `Class ${classStmt.name.text} extends ${httpRouterBaseClass} and must have a constructor`, - severity: 1, + range: classStmt.tokens.name.location.range, + message: `Class ${classStmt.tokens.name.text} extends ${httpRouterBaseClass} and must have a constructor`, + severity: DiagnosticSeverity.Error, code: 'HTTP_ROUTER_NO_CONSTRUCTOR', - }]); + }, { tags: [this.name] }); } }, }), { @@ -56,7 +59,7 @@ export class WebServerPlugin implements CompilerPlugin { }); } - beforeFileTranspile(event: BeforeFileTranspileEvent) { + beforePrepareFile(event: BeforePrepareFileEvent) { if (!isBrsFile(event.file)) { return; } @@ -84,7 +87,7 @@ export class WebServerPlugin implements CompilerPlugin { const classConstructor = this.getClassConstructor(classStmt) as MethodStatement; const method = routeInfo.method === 'ALL' ? '*' : routeInfo.method; - const stmt = new RawCodeStatement(`m.routes.push({ method: "${method}", path: "${routeInfo.route}", router: m, func: "${func.functionStatement?.name.text}" })`) + const stmt = new RawCodeStatement(`m.routes.push({ method: "${method}", path: "${routeInfo.route}", router: m, func: "${func.functionStatement!.getName(ParseMode.BrighterScript)}" })`) event.editor.arrayPush(classConstructor.func.body.statements, stmt); }, }), { @@ -98,7 +101,7 @@ export class WebServerPlugin implements CompilerPlugin { return false; } - const parentClass = classStmt.parentClassName.expression.name.text; + const parentClass = classStmt.parentClassName.getName(); return parentClass === httpRouterBaseClass; } @@ -140,8 +143,7 @@ export class WebServerPlugin implements CompilerPlugin { getClassConstructor(classStmt: ClassStatement) { return classStmt.body.find((stmt) => { const methodStmt = stmt as MethodStatement; - // @ts-ignore - if (methodStmt.name?.kind === TokenKind.New) { + if (methodStmt.tokens.name.text === 'new') { return stmt; } }); From 97a5b0dfe79ce2d4db55b18275debb7b0e828f61 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Tue, 23 Jul 2024 07:48:11 -0400 Subject: [PATCH 19/25] binding plugin --- tools/bs-plugins/bindings-plugin.ts | 87 ++++++++++++++++------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/tools/bs-plugins/bindings-plugin.ts b/tools/bs-plugins/bindings-plugin.ts index d3b699bca..79057f6f4 100644 --- a/tools/bs-plugins/bindings-plugin.ts +++ b/tools/bs-plugins/bindings-plugin.ts @@ -1,17 +1,19 @@ // Plugin to generate node bindings for AutoBind components import { - BeforeFileTranspileEvent, - BscFile, + AfterProvideFileEvent, + BeforePrepareFileEvent, CompilerPlugin, + ParseMode, XmlFile, + createSGScript, isBrsFile, isXmlFile, isXmlScope, util } from "brighterscript"; import path from "path"; -import { SGNode, SGScript } from "brighterscript/dist/parser/SGTypes"; +import { SGNode } from "brighterscript/dist/parser/SGTypes"; import { RawCodeStatement } from "./Classes/RawCodeStatement"; @@ -39,7 +41,12 @@ export class BindingsPlugin implements CompilerPlugin { private bindingsForFile: { [key: string]: Bindings } = {}; - afterFileParse(file: BscFile) { + afterProvideFile(event: AfterProvideFileEvent) { + if (event.files.length !== 1) { + return; + } + + const file = event.files[0]; if (!isXmlFile(file)) { return; } @@ -57,22 +64,19 @@ export class BindingsPlugin implements CompilerPlugin { program.setFile(bindingsFilePath, bindings_script_template); } - const scriptTag = new SGScript(); - scriptTag.type = "text/brightscript" - scriptTag.uri = util.getRokuPkgPath(bindingsFilePath); - if (!file.ast.component!.scripts) { - file.ast.component!.scripts = []; - } - file.ast.component!.scripts.push(scriptTag); + const scriptTag = createSGScript({ + type: "text/brightscript", + uri: util.sanitizePkgPath(bindingsFilePath) + }); + file.ast.componentElement!.addChild(scriptTag); this.deleteBindingsInFields(file); - this.deleteBindingsInChildPropsNode(file.ast.component!.children); - + this.deleteBindingsInChildPropsNode(file.ast.componentElement!.childrenElement); file.parser.invalidateReferences(); } - beforeFileTranspile(event: BeforeFileTranspileEvent) { - if (!isBrsFile(event.file) || !event.file.pkgPath.endsWith('_bindings.bs')) { + beforePrepareFile(event: BeforePrepareFileEvent) { + if (!isBrsFile(event.file) || !event.file.pkgPath.endsWith('_bindings.brs')) { return } @@ -92,7 +96,7 @@ export class BindingsPlugin implements CompilerPlugin { } const bindingsFunction = event.file.callables[0]; - if (bindingsFunction.functionStatement.name.text !== bindings_function_name) { + if (bindingsFunction.functionStatement.getName(ParseMode.BrightScript) !== bindings_function_name) { throw new Error(`Bindings file ${event.file.pkgPath} should have exactly one function named ${bindings_function_name}`); } @@ -125,7 +129,7 @@ export class BindingsPlugin implements CompilerPlugin { } getBindingsForXmlFile(xmlFile: XmlFile): Bindings { - const isAutoBindComponent = !!xmlFile.ast.component?.api?.fields?.find((field) => { + const isAutoBindComponent = !!xmlFile.ast.componentElement?.interfaceElement?.fields?.find((field) => { return field.id === 'binding_done'; }) && xmlFile.componentName.text !== 'AutoBind'; @@ -133,16 +137,16 @@ export class BindingsPlugin implements CompilerPlugin { return { isAutoBindComponent, fields: {}, childProps: {} }; } - const fields = xmlFile.ast.component?.api?.fields?.filter((field) => { - return field.attributes.find((attr) => attr.key.text === 'bind'); + const fields = xmlFile.ast.componentElement?.interfaceElement?.fields?.filter((field) => { + return field.attributes.find((attr) => attr.key === 'bind'); }); const childProps: ChildProps = {}; - this.getChildBindings(childProps, xmlFile.ast.component?.children); + this.getChildBindings(childProps, xmlFile.ast.componentElement?.childrenElement); const bindingFields = fields?.reduce((acc, field) => { - const bindAttr = field.attributes.find((attr) => attr.key.text === 'bind'); - acc[field.id] = bindAttr!.value.text; + const bindAttr = field.attributes.find((attr) => attr.key === 'bind'); + acc[field.id] = bindAttr!.value!; return acc; }, {} as { [key: string]: string }) || {}; @@ -154,30 +158,30 @@ export class BindingsPlugin implements CompilerPlugin { return; } if (node.id) { - const props = node.attributes.filter((attr) => attr.value.text.startsWith('bind:')); + const props = node.attributes.filter((attr) => attr.value!.startsWith('bind:')); if (props.length) { if (!bindings[node.id]) { bindings[node.id] = {}; } for (let i = 0; i < props.length; i++) { const prop = props[i]; - bindings[node.id][prop.key.text] = prop.value.text.replace('bind:', ''); + bindings[node.id][prop.key] = prop.value!.replace('bind:', ''); } } } - if (node.children) { - for (let i = 0; i < node.children.length; i++) { - const child = node.children[i]; - this.getChildBindings(bindings, child); - } + for (let i = 0; i < node.elements.length; i++) { + const child = node.elements[i]; + this.getChildBindings(bindings, child); } } deleteBindingsInFields(xmlFile: XmlFile) { - xmlFile.ast.component!.api!.fields.forEach((field) => { - field.attributes = field.attributes.filter((attr) => { - return attr.key.text !== 'bind'; - }); + const fields = xmlFile.ast.componentElement?.interfaceElement?.fields; + if (!fields) { + return; + } + fields.forEach((field) => { + field.removeAttribute('bind'); }); } @@ -185,15 +189,18 @@ export class BindingsPlugin implements CompilerPlugin { if (!node) { return; } - node.attributes = node.attributes.filter((attr) => { - return !attr.value.text.startsWith('bind:'); - }); - if (node.children) { - for (let i = 0; i < node.children.length; i++) { - const child = node.children[i]; - this.deleteBindingsInChildPropsNode(child); + if (node.attributes) { + for (let i = 0; i < node.attributes.length; i++) { + const attr = node.attributes[i]; + if (attr.value?.startsWith('bind:')) { + node.removeAttribute(attr.key); + } } } + for (let i = 0; i < node.elements.length; i++) { + const child = node.elements[i]; + this.deleteBindingsInChildPropsNode(child); + } } } From 61d04f4e31160ce1cc57bdf2169f16315ed88c14 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Tue, 23 Jul 2024 17:27:48 -0400 Subject: [PATCH 20/25] plugin fix --- tools/bs-plugins/bindings-plugin.ts | 2 +- tools/bs-plugins/logger-plugin.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/bs-plugins/bindings-plugin.ts b/tools/bs-plugins/bindings-plugin.ts index 79057f6f4..1bf7ab61e 100644 --- a/tools/bs-plugins/bindings-plugin.ts +++ b/tools/bs-plugins/bindings-plugin.ts @@ -190,7 +190,7 @@ export class BindingsPlugin implements CompilerPlugin { return; } if (node.attributes) { - for (let i = 0; i < node.attributes.length; i++) { + for (let i = node.attributes.length - 1; i >= 0; i--) { const attr = node.attributes[i]; if (attr.value?.startsWith('bind:')) { node.removeAttribute(attr.key); diff --git a/tools/bs-plugins/logger-plugin.ts b/tools/bs-plugins/logger-plugin.ts index 749e5298c..bd77dd3ee 100644 --- a/tools/bs-plugins/logger-plugin.ts +++ b/tools/bs-plugins/logger-plugin.ts @@ -61,7 +61,13 @@ export class LoggerPlugin implements CompilerPlugin { const visitor = createVisitor({ ExpressionStatement: (statement) => { const expression = statement.expression as CallExpression; + if (!expression) { + return; + } const callee = expression.callee as DottedGetExpression; + if (!callee || !callee.getName) { + return; + } const funcName = callee.getName(ParseMode.BrightScript); if (funcName && logFunctionKeys.includes(funcName)) { const argCount = expression.args.length + 1; // +1 for the file path @@ -102,7 +108,13 @@ export class LoggerPlugin implements CompilerPlugin { const visitor = createVisitor({ ExpressionStatement: (statement) => { const expression = statement.expression as CallExpression; + if (!expression) { + return; + } const callee = expression.callee as DottedGetExpression; + if (!callee || !callee.getName) { + return; + } const funcName = callee.getName(ParseMode.BrightScript); if (funcName && logFunctionKeys.includes(funcName)) { const args = expression.args; From 7569b49e78800458bb7fd34b47ab451171f0bf55 Mon Sep 17 00:00:00 2001 From: Brahim Hadriche Date: Tue, 23 Jul 2024 17:39:54 -0400 Subject: [PATCH 21/25] Some changes --- .../BootstrapScene/BootstrapScene.bs | 2 + playlet-app/src/source/Main.bs | 2 + .../components/AppController/AppController.bs | 8 +-- .../src/components/ChannelView/ChannelView.bs | 12 +++++ .../src/components/ContextMenu/ContextMenu.bs | 2 +- playlet-lib/src/components/Logger/Logger.bs | 6 ++- playlet-lib/src/components/NavBar/NavBar.bs | 7 ++- .../BookmarksScreen/BookmarksScreen.bs | 2 +- .../InvidiousInstanceTestingTask.bs | 10 +++- .../ApplicationInfo/ApplicationInfo.bs | 10 ++-- .../components/Services/Dash/DashManifest.bs | 4 ++ .../Services/Invidious/Invidious.bs | 4 +- .../Services/Invidious/InvidiousService.bs | 15 ++++-- .../Services/LoungeService/LongPoller.bs | 3 +- .../Services/LoungeService/LoungeApi.bs | 13 +++-- .../Services/LoungeService/LoungeService.bs | 4 +- .../Services/Preferences/Preferences.bs | 6 +-- .../ProfilesService/ProfilesService.bs | 2 +- .../ProfilesVerifyTokensTask.bs | 4 +- .../SearchHistory/SearchHistoryUtils.bs | 6 +-- .../SponsorBlock/SponsorBlockService.bs | 3 ++ .../src/components/VideoFeed/VideoRowList.bs | 2 +- .../components/VideoQueue/VideoQueueView.bs | 2 +- .../src/components/Web/Dial/DialServer.bs | 4 +- .../Middleware/BookmarksRouter.bs | 2 + .../PlayletWebServer/Middleware/DashRouter.bs | 5 ++ .../PlayletWebServer/Middleware/DialRouter.bs | 11 ++++ .../Middleware/HomeLayoutRouter.bs | 2 + .../Middleware/InvidiousRouter.bs | 4 ++ .../Middleware/PlayletLibUrlsRouter.bs | 2 + .../Middleware/PreferencesRouter.bs | 2 + .../Middleware/ProfilesRouter.bs | 8 ++- .../Middleware/SearchHistoryRouter.bs | 2 + .../Middleware/StateApiRouter.bs | 5 ++ .../Middleware/VideoQueueRouter.bs | 4 ++ .../PlayletWebServer/Middleware/ViewRouter.bs | 3 ++ .../Web/PlayletWebServer/PlayletWebServer.bs | 2 +- .../Web/WebServer/Http/HttpConnection.bs | 51 +++++++++++-------- .../Web/WebServer/Http/HttpRequest.bs | 21 ++++---- .../Web/WebServer/Http/HttpServer.bs | 29 ++++++----- .../Web/WebServer/Http/HttpSettings.bs | 4 +- .../Web/WebServer/Http/HttpUtils.bs | 7 ++- .../WebServer/Middleware/EtagMiddleware.bs | 2 + .../Web/WebServer/Middleware/EtagUtils.bs | 3 ++ .../Middleware/HttpStaticFilesRouter.bs | 32 ++++++------ .../src/components/Web/WebServer/WebServer.bs | 4 +- .../WebSockets/WebSocketConnection.bs | 6 ++- .../WebServer/WebSockets/WebSocketFrame.bs | 1 + .../parts/AutoBind/AutoBind.part.bs | 10 ++-- 49 files changed, 237 insertions(+), 118 deletions(-) diff --git a/playlet-app/src/components/BootstrapScene/BootstrapScene.bs b/playlet-app/src/components/BootstrapScene/BootstrapScene.bs index 1ee2e0ab2..7a2025dec 100644 --- a/playlet-app/src/components/BootstrapScene/BootstrapScene.bs +++ b/playlet-app/src/components/BootstrapScene/BootstrapScene.bs @@ -20,6 +20,8 @@ function Init() as void LoadPlayletLib() end function +' TODO:P2 remove after fix +' bs:disable-next-line LINT2004 function GetPlayletLibUrls() as object #if DEBUG debug = { type: "debug-zip", link: Manifest.ReadValue("playlet_lib_zip_debug_url") } diff --git a/playlet-app/src/source/Main.bs b/playlet-app/src/source/Main.bs index 756feea34..56d20175f 100644 --- a/playlet-app/src/source/Main.bs +++ b/playlet-app/src/source/Main.bs @@ -49,6 +49,8 @@ function Main(args as object) as void input.setMessagePort(port) systemLog = CreateObject("roSystemLog") + ' TODO:P2 remove after fix + ' bs:disable-next-line 1140 systemLog.SetMessagePort(port) ' Although all types are enabled, they are filtered in Playlet Lib to avoid spamming the logs systemLog.EnableType("http.connect") diff --git a/playlet-lib/src/components/AppController/AppController.bs b/playlet-lib/src/components/AppController/AppController.bs index 146d2b7f4..c6c877ea9 100644 --- a/playlet-lib/src/components/AppController/AppController.bs +++ b/playlet-lib/src/components/AppController/AppController.bs @@ -21,18 +21,18 @@ end function function PushScreen(node as object) m.stack.appendChild(node) - FocusTopScreen(invalid) + FocusTopScreen() end function -function PopScreen(_unused as dynamic) +function PopScreen() childCount = m.stack.getChildCount() if childCount > 1 m.stack.removeChildIndex(childCount - 1) - FocusTopScreen(invalid) + FocusTopScreen() end if end function -function FocusTopScreen(_unused as dynamic) +function FocusTopScreen() childCount = m.stack.getChildCount() topScreen = m.stack.getChild(childCount - 1) NodeSetFocus(topScreen, true) diff --git a/playlet-lib/src/components/ChannelView/ChannelView.bs b/playlet-lib/src/components/ChannelView/ChannelView.bs index 113f8c42f..8f26389ba 100644 --- a/playlet-lib/src/components/ChannelView/ChannelView.bs +++ b/playlet-lib/src/components/ChannelView/ChannelView.bs @@ -178,21 +178,33 @@ end function function InitializeTabs() m.tabs = { + ' TODO:P2 remove after fix + ' bs:disable-next-line LINT1001 "videos": function(authorId as string, author as string) as object return CreateChannelFeed("Videos", "channel_videos", authorId, author) end function + ' TODO:P2 remove after fix + ' bs:disable-next-line LINT1001 "shorts": function(authorId as string, author as string) as object return CreateChannelFeed("Shorts", "channel_shorts", authorId, author) end function + ' TODO:P2 remove after fix + ' bs:disable-next-line LINT1001 "streams": function(authorId as string, author as string) as object return CreateChannelFeed("Live", "channel_streams", authorId, author) end function + ' TODO:P2 remove after fix + ' bs:disable-next-line LINT1001 "releases": function(authorId as string, author as string) as object return CreateChannelFeed("Releases", "channel_releases", authorId, author) end function + ' TODO:P2 remove after fix + ' bs:disable-next-line LINT1001 "podcasts": function(authorId as string, author as string) as object return CreateChannelFeed("Podcasts", "channel_podcasts", authorId, author) end function + ' TODO:P2 remove after fix + ' bs:disable-next-line LINT1001 "playlists": function(authorId as string, author as string) as object return CreateChannelFeed("Playlists", "channel_playlists", authorId, author) end function diff --git a/playlet-lib/src/components/ContextMenu/ContextMenu.bs b/playlet-lib/src/components/ContextMenu/ContextMenu.bs index 3a74f4596..be63c3de4 100644 --- a/playlet-lib/src/components/ContextMenu/ContextMenu.bs +++ b/playlet-lib/src/components/ContextMenu/ContextMenu.bs @@ -87,7 +87,7 @@ function Init() m.showAnimation = m.top.findNode("showAnimation") end function -function Show(_unused as dynamic) +function Show() m.optionsList.ObserveField("itemSelected", FuncName(OnItemSelected)) m.showAnimation.control = "start" end function diff --git a/playlet-lib/src/components/Logger/Logger.bs b/playlet-lib/src/components/Logger/Logger.bs index e5126c0f9..8f7e494e2 100644 --- a/playlet-lib/src/components/Logger/Logger.bs +++ b/playlet-lib/src/components/Logger/Logger.bs @@ -21,12 +21,12 @@ function Init() #end if end function -function StartLogger(logger as object, logLevel = LogLevel.Info as LogLevel) as void +function StartLogger(logger as object, level = LogLevel.Info as LogLevel) as void if m.global.logger <> invalid return end if - logger.logLevel = logLevel + logger.logLevel = level m.global.addFields({ logger: logger }) logger.control = "run" end function @@ -55,6 +55,8 @@ function LoggerLoop() appMemoryMonitor = CreateObject("roAppMemoryMonitor") if appMemoryMonitor <> invalid and FindMemberFunction(appMemoryMonitor, "EnableMemoryWarningEvent") <> invalid + ' TODO:P2 remove after fix + ' bs:disable-next-line 1140 appMemoryMonitor.SetMessagePort(port) appMemoryMonitor.EnableMemoryWarningEvent(true) end if diff --git a/playlet-lib/src/components/NavBar/NavBar.bs b/playlet-lib/src/components/NavBar/NavBar.bs index 091737ff9..b1310bd1d 100644 --- a/playlet-lib/src/components/NavBar/NavBar.bs +++ b/playlet-lib/src/components/NavBar/NavBar.bs @@ -2,6 +2,10 @@ import "pkg:/source/utils/FocusManagement.bs" import "pkg:/source/utils/RemoteKeys.bs" import "pkg:/source/utils/Types.bs" +interface NavBarComponent extends roSGNode + itemContent as roSGNodeNavBarItemContent +end interface + function Init() m.lastIsInFocusChain = false m.top.focusable = true @@ -30,7 +34,8 @@ function ResizeNavBar() as void return end if - component = CreateObject("roSGNode", m.itemsList.itemComponentName) + ' bs:disable-next-line LINT1001 + component = CreateObject("roSGNode", m.itemsList.itemComponentName) as NavBarComponent itemSize = m.itemsList.itemSize minWidth = itemSize[0] items = content.getChildren(-1, 0) diff --git a/playlet-lib/src/components/Screens/BookmarksScreen/BookmarksScreen.bs b/playlet-lib/src/components/Screens/BookmarksScreen/BookmarksScreen.bs index f0301e629..fcceae293 100644 --- a/playlet-lib/src/components/Screens/BookmarksScreen/BookmarksScreen.bs +++ b/playlet-lib/src/components/Screens/BookmarksScreen/BookmarksScreen.bs @@ -44,7 +44,7 @@ function OnVisibleChange() end if end function -function Refresh(_unused as dynamic) +function Refresh() m.isDirty = true OnBookmarksChange() end function diff --git a/playlet-lib/src/components/Screens/SettingsScreen/InvidiousInstance/InvidiousInstanceTesting/InvidiousInstanceTestingTask.bs b/playlet-lib/src/components/Screens/SettingsScreen/InvidiousInstance/InvidiousInstanceTesting/InvidiousInstanceTestingTask.bs index 69bae1e54..5a39796bf 100644 --- a/playlet-lib/src/components/Screens/SettingsScreen/InvidiousInstance/InvidiousInstanceTesting/InvidiousInstanceTestingTask.bs +++ b/playlet-lib/src/components/Screens/SettingsScreen/InvidiousInstance/InvidiousInstanceTesting/InvidiousInstanceTestingTask.bs @@ -5,6 +5,13 @@ import "pkg:/source/utils/ErrorUtils.bs" import "pkg:/source/utils/Locale.bs" import "pkg:/source/utils/StringUtils.bs" +interface ifTestNode extends roSGNodeContentNode + func as function + state as string + details as string + duration as integer +end interface + @asynctask function InvidiousInstanceTestingTask(input as object) as object instance = input.instance @@ -37,7 +44,8 @@ function PrepareTests() as object end function function CreateTestNode(title as string, func as function) as object - testNode = CreateObject("roSGNode", "ContentNode") + ' bs:disable-next-line LINT1001 + testNode = CreateObject("roSGNode", "ContentNode") as ifTestNode testNode.title = title testNode.AddFields({ func: FuncName(func) diff --git a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs index e49b2a192..02b20344f 100644 --- a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs +++ b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs @@ -14,23 +14,23 @@ function Init() m.service = new ApplicationInfo(m.top) end function -function GetAppInfo(_unused as dynamic) as roAssociativeArray +function GetAppInfo() as roAssociativeArray return m.service.GetAppInfo() end function -function GetDeviceInfo(_unused as dynamic) as roAssociativeArray +function GetDeviceInfo() as roAssociativeArray return m.service.GetDeviceInfo() end function -function GetUserCountryCode(_unused as dynamic) as string +function GetUserCountryCode() as string return m.service.GetUserCountryCode() end function -function GetLocalIpAddress(_unused as dynamic) as dynamic +function GetLocalIpAddress() as dynamic return m.service.GetLocalIpAddress() end function -function GetLatestPlayletLibVersion(_unused as dynamic) as dynamic +function GetLatestPlayletLibVersion() as dynamic if not StringUtils.IsNullOrEmpty(m.top.lib_version_latest) return m.top.lib_version_latest end if diff --git a/playlet-lib/src/components/Services/Dash/DashManifest.bs b/playlet-lib/src/components/Services/Dash/DashManifest.bs index a03bd8996..0eb0cb8f5 100644 --- a/playlet-lib/src/components/Services/Dash/DashManifest.bs +++ b/playlet-lib/src/components/Services/Dash/DashManifest.bs @@ -7,6 +7,10 @@ class DashManifest public invidiousInstance as dynamic + private utils as Http.Utils + private urlRegex as roRegex + private colorInfo as object + function new(invidiousInstance as string) m.invidiousInstance = invidiousInstance diff --git a/playlet-lib/src/components/Services/Invidious/Invidious.bs b/playlet-lib/src/components/Services/Invidious/Invidious.bs index 9fecea2c4..cad7558bd 100644 --- a/playlet-lib/src/components/Services/Invidious/Invidious.bs +++ b/playlet-lib/src/components/Services/Invidious/Invidious.bs @@ -7,11 +7,11 @@ function Init() m.service = new Invidious.InvidiousService(m.top) end function -function GetCurrentInstance(_unused as dynamic) as string +function GetCurrentInstance() as string return m.service.GetInstance() end function -function GetAuthorizeTokenLink(_unused as dynamic) as dynamic +function GetAuthorizeTokenLink() as dynamic return m.service.GetAuthorizeTokenLink() end function diff --git a/playlet-lib/src/components/Services/Invidious/InvidiousService.bs b/playlet-lib/src/components/Services/Invidious/InvidiousService.bs index 8af2baed5..390609e48 100644 --- a/playlet-lib/src/components/Services/Invidious/InvidiousService.bs +++ b/playlet-lib/src/components/Services/Invidious/InvidiousService.bs @@ -37,9 +37,13 @@ namespace Invidious const ERROR_NOT_AUTHENTICATED = "Not authenticated" class InvidiousService - public invidiousNode as object + public invidiousNode as roSGNodeInvidious - function new(invidiousNode as object) + private _userCountryCode as dynamic + private preferences as roSGNodePreferences + private endpoints as object + + function new(invidiousNode as roSGNodeInvidious) m.invidiousNode = invidiousNode end function @@ -64,7 +68,8 @@ namespace Invidious function GetInstance() as string if m.preferences = invalid - m.preferences = m.invidiousNode.preferences + ' bs:disable-next-line LINT1001 + m.preferences = m.invidiousNode.preferences as roSGNodePreferences end if instance = m.preferences["invidious.instance"] if not StringUtils.IsNullOrEmpty(instance) @@ -136,6 +141,7 @@ namespace Invidious if tryCount > 1 request.TryCount(tryCount) + ' bs:disable-next-line LINT1001 request.RetryCallback(function(context as object) as boolean response = context.response ' In some cases, video info requests return "HTTP/0.9 when not allowed" errors. @@ -314,7 +320,8 @@ namespace Invidious response = request.Await() responseHandler = invalid - if IsString(endpoint.responseHandler) and m.DoesExist(endpoint.responseHandler) + ' bs:disable-next-line LINT1001 + if IsString(endpoint.responseHandler) and (m as ifAssociativeArray).DoesExist(endpoint.responseHandler) responseHandler = endpoint.responseHandler else responseHandler = "DefaultHandler" diff --git a/playlet-lib/src/components/Services/LoungeService/LongPoller.bs b/playlet-lib/src/components/Services/LoungeService/LongPoller.bs index 353163cbc..060cd4ed7 100644 --- a/playlet-lib/src/components/Services/LoungeService/LongPoller.bs +++ b/playlet-lib/src/components/Services/LoungeService/LongPoller.bs @@ -16,13 +16,14 @@ class LongPoller ' Socket stuff for long polling private socket private socket_buffer - private socket_state = HttpResponseState.INIT + private socket_state as HttpResponseState = HttpResponseState.INIT private socket_chunk_size = 0 private socket_timer private status_code = 0 private status_text private headers + private url function new() m.socket_timer = CreateObject("roTimespan") diff --git a/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs b/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs index 683017147..d7084dada 100644 --- a/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs +++ b/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs @@ -33,11 +33,12 @@ class LoungeApi public sessionId public gSessionId public devices + public poller private ofs private lastProcessedCommandIndex = -1 - private poller private outgoingMessagesRequests + private dateTime as roDateTime function new(loungeServiceNode as object, videoQueueNode as object, notificationsNode as object, invidiousNode as object) m.loungeServiceNode = loungeServiceNode @@ -242,8 +243,8 @@ class LoungeApi chunk = m.ConsumeNewLines(chunk) newLineIndex = chunk.InStr(`\n`) while newLineIndex > 0 - payloadSize = chunk.Left(newLineIndex).trim() - payloadSize = payloadSize.ToInt() + payloadSizeStr = chunk.Left(newLineIndex).trim() + payloadSize = payloadSizeStr.ToInt() payload = chunk.Mid(newLineIndex + 1, payloadSize) commands = ParseJson(payload) m.ProcessCommands(commands, messagesToSend) @@ -298,7 +299,8 @@ class LoungeApi end if handler = COMMAND_HANDLER_PREFIX + commandType - if m.DoesExist(handler) + ' bs:disable-next-line LINT1001 + if (m as roAssociativeArray).DoesExist(handler) LogInfo(commandIndex, commandType) m[handler](commandIndex, commandType, commandArgs, messagesToSend) else @@ -542,7 +544,8 @@ class LoungeApi end for loungeData = FormatJson(loungeData) - RegistryUtils.Write(RegistryUtils.LAST_LOUNGE_DATA, loungeData) + ' TODO:P0 check if this is valid usage + RegistryUtils.Write(RegistryUtils.LAST_LOUNGE_DATA, loungeData as string) end function function DisconnectFromLastLounge() as void diff --git a/playlet-lib/src/components/Services/LoungeService/LoungeService.bs b/playlet-lib/src/components/Services/LoungeService/LoungeService.bs index 8166cf336..52b183e45 100644 --- a/playlet-lib/src/components/Services/LoungeService/LoungeService.bs +++ b/playlet-lib/src/components/Services/LoungeService/LoungeService.bs @@ -13,7 +13,7 @@ function Init() m.top.deviceName = "Playlet on " + deviceFriendlyName end function -function StartService(_unused as dynamic) as boolean +function StartService() as boolean if m.top.isRunning = true return true end if @@ -22,7 +22,7 @@ function StartService(_unused as dynamic) as boolean return true end function -function StopService(_unused as dynamic) as void +function StopService() as void if m.top.isRunning = false return end if diff --git a/playlet-lib/src/components/Services/Preferences/Preferences.bs b/playlet-lib/src/components/Services/Preferences/Preferences.bs index a837206a4..b8f85295f 100644 --- a/playlet-lib/src/components/Services/Preferences/Preferences.bs +++ b/playlet-lib/src/components/Services/Preferences/Preferences.bs @@ -57,7 +57,7 @@ function LoadUserPreferencesFromRegistry() if userPrefs = invalid userPrefs = {} else - userPrefs = ParseJson(userPrefs) + userPrefs = ParseJson(userPrefs as string) end if ' Step 2: Migrate existing preferences to new format (if needed) @@ -142,7 +142,7 @@ function ApplyToUserPreferences(userPrefs as object, model as object) as boolean return isDirty end function -function GetUserPreferences(_unused as dynamic) as object +function GetUserPreferences() as object userPrefs = {} prefsFields = m.top.preferenceFields for each key in prefsFields @@ -163,7 +163,7 @@ function ApplyUserPreferences(preferences as object) as void SaveUserPreferencesToRegistry() end function -function ClearUserPreferences(_unused as dynamic) as void +function ClearUserPreferences() as void userPrefs = {} ApplyDefaultsToUserPreferences(userPrefs) ApplyUserPreferences(userPrefs) diff --git a/playlet-lib/src/components/Services/ProfilesService/ProfilesService.bs b/playlet-lib/src/components/Services/ProfilesService/ProfilesService.bs index e97bdde0b..83aeb4c92 100644 --- a/playlet-lib/src/components/Services/ProfilesService/ProfilesService.bs +++ b/playlet-lib/src/components/Services/ProfilesService/ProfilesService.bs @@ -31,7 +31,7 @@ function LoadProfilesFromRegistry() currentProfile: invalid } else - userProfiles = ParseJson(userProfiles) + userProfiles = ParseJson(userProfiles as string) end if ' Step 2: Migrate existing profiles to new format (if needed) diff --git a/playlet-lib/src/components/Services/ProfilesService/ProfilesVerifyTokensTask.bs b/playlet-lib/src/components/Services/ProfilesService/ProfilesVerifyTokensTask.bs index 1353521fb..361ce7249 100644 --- a/playlet-lib/src/components/Services/ProfilesService/ProfilesVerifyTokensTask.bs +++ b/playlet-lib/src/components/Services/ProfilesService/ProfilesVerifyTokensTask.bs @@ -25,9 +25,9 @@ function ProfilesVerifyTokensTask(input as object) as object for each profileNode in invalidProfiles profileNames.push(profileNode.username) end for - profileNames = profileNames.join(", ") + profileNamesStr = profileNames.join(", ") - message = Tr(Locale.Dialogs.UserLoggedOutMessage).Replace("\n", `\n`).Replace("%1", profileNames) + message = Tr(Locale.Dialogs.UserLoggedOutMessage).Replace("\n", `\n`).Replace("%1", profileNamesStr) DialogUtils.ShowDialog(message, Tr(Locale.Dialogs.UserLoggedOut)) return invalid diff --git a/playlet-lib/src/components/Services/SearchHistory/SearchHistoryUtils.bs b/playlet-lib/src/components/Services/SearchHistory/SearchHistoryUtils.bs index 78d592c7e..2b51fb39d 100644 --- a/playlet-lib/src/components/Services/SearchHistory/SearchHistoryUtils.bs +++ b/playlet-lib/src/components/Services/SearchHistory/SearchHistoryUtils.bs @@ -21,9 +21,9 @@ namespace SearchHistoryUtils history.Pop() end if - history = FormatJson(history) + historyStr = FormatJson(history) - RegistryUtils.Write(RegistryUtils.SEARCH_HISTORY, history) + RegistryUtils.Write(RegistryUtils.SEARCH_HISTORY, historyStr) end function function GetSaved(preferencesNode as object, q as string) as object @@ -44,7 +44,7 @@ namespace SearchHistoryUtils return result end function - function GetAllSaved(preferencesNode as object) as object + function GetAllSaved(preferencesNode as object) as string[] seachHistoryEnabled = preferencesNode["search_history.enabled"] if not seachHistoryEnabled return [] diff --git a/playlet-lib/src/components/Services/SponsorBlock/SponsorBlockService.bs b/playlet-lib/src/components/Services/SponsorBlock/SponsorBlockService.bs index 1fb28ee48..b3cf95163 100644 --- a/playlet-lib/src/components/Services/SponsorBlock/SponsorBlockService.bs +++ b/playlet-lib/src/components/Services/SponsorBlock/SponsorBlockService.bs @@ -7,6 +7,9 @@ namespace SponsorBlock const VIEWED_SEGMENT_ENDPOINT = "/api/viewedVideoSponsorTime" class SponsorBlockService + + private sponsorBlockConfig as object + function new() ' TODO:P2 this is being read and parsed on every skipped segment. It should be cached. m.sponsorBlockConfig = ParseJson(ReadAsciiFile("libpkg:/config/sponsorblock_config.json5")) diff --git a/playlet-lib/src/components/VideoFeed/VideoRowList.bs b/playlet-lib/src/components/VideoFeed/VideoRowList.bs index c11d05f07..4a605f3f8 100644 --- a/playlet-lib/src/components/VideoFeed/VideoRowList.bs +++ b/playlet-lib/src/components/VideoFeed/VideoRowList.bs @@ -202,7 +202,7 @@ function OpenPlaylistChannel(playlist as object) as void ChannelUtils.Open(channel) end function -function Refresh(_unused as dynamic) +function Refresh() InitContent() end function diff --git a/playlet-lib/src/components/VideoQueue/VideoQueueView.bs b/playlet-lib/src/components/VideoQueue/VideoQueueView.bs index aebe4a3cb..ab8d24a47 100644 --- a/playlet-lib/src/components/VideoQueue/VideoQueueView.bs +++ b/playlet-lib/src/components/VideoQueue/VideoQueueView.bs @@ -23,7 +23,7 @@ function Init() m.videosDetailsToLoad = [] end function -function Show(_unused as dynamic) +function Show() m.showAnimation.control = "start" end function diff --git a/playlet-lib/src/components/Web/Dial/DialServer.bs b/playlet-lib/src/components/Web/Dial/DialServer.bs index 239df6da3..f4d784ccf 100644 --- a/playlet-lib/src/components/Web/Dial/DialServer.bs +++ b/playlet-lib/src/components/Web/Dial/DialServer.bs @@ -7,7 +7,7 @@ function Init() m.top.functionName = "DialServerLoop" end function -function StartServer(_unused as dynamic) as boolean +function StartServer() as boolean if m.top.isRunning = true return true end if @@ -16,7 +16,7 @@ function StartServer(_unused as dynamic) as boolean return true end function -function StopServer(_unused as dynamic) as void +function StopServer() as void if m.top.isRunning = false return end if diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/BookmarksRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/BookmarksRouter.bs index ebfb2fecb..77dbbb2bd 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/BookmarksRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/BookmarksRouter.bs @@ -5,6 +5,8 @@ namespace Http class BookmarksRouter extends HttpRouter + private bookmarksService as roSGNodeBookmarksService + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DashRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DashRouter.bs index 6aa967d04..82401e90d 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DashRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DashRouter.bs @@ -5,6 +5,11 @@ import "pkg:/source/utils/Types.bs" namespace Http class DashRouter extends HttpRouter + + private invidiousNode as roSGNodeInvidious + private invidiousService as Invidious.InvidiousService + private dashManifest as DashManifest + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs index 865f7992f..ce3606bca 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs @@ -4,6 +4,17 @@ namespace Http class DialRouter extends HttpRouter + private serverAddress + private scene as object + private loungeService as roSGNodeLoungeService + private deviceId as string + private deviceName as string + + private _dialXml as string + private _dialYouTubeXml as string + private _dialYoutubeScreenId as string + private _dialYoutubeLoungeToken as string + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/HomeLayoutRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/HomeLayoutRouter.bs index 9caff68b3..a6ec8869a 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/HomeLayoutRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/HomeLayoutRouter.bs @@ -4,6 +4,8 @@ namespace Http class HomeLayoutRouter extends HttpRouter + private preferencesNode as roSGNodePreferences + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/InvidiousRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/InvidiousRouter.bs index 2ce58ad97..d53ea949f 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/InvidiousRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/InvidiousRouter.bs @@ -5,6 +5,10 @@ namespace Http class InvidiousRouter extends HttpRouter + private profilesNode as roSGNodeProfilesService + private invidiousNode as roSGNodeInvidious + private invidiousService as Invidious.InvidiousService + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PlayletLibUrlsRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PlayletLibUrlsRouter.bs index abdc05795..9c5ce3195 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PlayletLibUrlsRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PlayletLibUrlsRouter.bs @@ -4,6 +4,8 @@ namespace Http class PlayletLibUrlsRouter extends HttpRouter + private scene as object + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PreferencesRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PreferencesRouter.bs index 284c7e524..e648e7564 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PreferencesRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/PreferencesRouter.bs @@ -2,6 +2,8 @@ namespace Http class PreferencesRouter extends HttpRouter + private preferencesNode as roSGNodePreferences + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ProfilesRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ProfilesRouter.bs index 8c0bb07d8..cf9245d0e 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ProfilesRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ProfilesRouter.bs @@ -2,10 +2,14 @@ namespace Http class ProfilesRouter extends HttpRouter - function new(server as object) + private profilesNode as roSGNodeProfilesService + private profilesContent as roSGNodeContentNode + + function new(server as HttpServer) super() - m.profilesNode = server.task.profilesService + ' bs:disable-next-line LINT1001 + m.profilesNode = server.task.profilesService as roSGNodeProfilesService m.profilesContent = m.profilesNode.content.getChild(0) end function diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/SearchHistoryRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/SearchHistoryRouter.bs index 62946ac05..8da126b2e 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/SearchHistoryRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/SearchHistoryRouter.bs @@ -4,6 +4,8 @@ namespace Http class SearchHistoryRouter extends HttpRouter + private preferencesNode as roSGNodePreferences + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/StateApiRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/StateApiRouter.bs index 1a5e6e9f4..fb19595d2 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/StateApiRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/StateApiRouter.bs @@ -4,6 +4,11 @@ namespace Http class StateApiRouter extends HttpRouter + private applicationInfoNode as roSGNodeApplicationInfo + private invidiousNode as roSGNodeInvidious + private preferencesNode as roSGNodePreferences + private profilesNode as roSGNodeProfilesService + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/VideoQueueRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/VideoQueueRouter.bs index 6617f9da9..690216b76 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/VideoQueueRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/VideoQueueRouter.bs @@ -6,6 +6,10 @@ namespace Http class VideoQueueRouter extends HttpRouter + private invidiousNode as roSGNodeInvidious + private invidiousService as Invidious.InvidiousService + private videoQueueNode as roSGNodeVideoQueue + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ViewRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ViewRouter.bs index 12a38a272..3f3788932 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ViewRouter.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/ViewRouter.bs @@ -7,6 +7,9 @@ namespace Http class ViewRouter extends HttpRouter + private appController as roSGNodeAppController + private videoQueue as roSGNodeVideoQueue + function new(server as object) super() diff --git a/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs b/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs index 69f12cb79..1674fade0 100644 --- a/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs +++ b/playlet-lib/src/components/Web/PlayletWebServer/PlayletWebServer.bs @@ -24,7 +24,7 @@ function Init() m.top.serverName = "Playlet Web Server" end function -function GetServerAddress(_unused as dynamic) as dynamic +function GetServerAddress() as dynamic port = m.top.port ip = m.top.applicationInfo@.GetLocalIpAddress() if StringUtils.IsNullOrEmpty(ip) diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpConnection.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpConnection.bs index 8fc5a3331..9e45092a3 100644 --- a/playlet-lib/src/components/Web/WebServer/Http/HttpConnection.bs +++ b/playlet-lib/src/components/Web/WebServer/Http/HttpConnection.bs @@ -9,15 +9,23 @@ namespace Http const BUFSIZE = 65536 class HttpConnection + public state = HttpConnectionState.INIT as HttpConnectionState + public socket as roStreamSocket + public id = "" + public close = true + public ws_upgrade = false + private total_received = 0 private total_sent = 0 - private id = "" - private close = true - private ws_upgrade = false - private state = Http.HttpConnectionState.INIT private server as HttpServer private settings as HttpSettings + private addr as roSocketAddress + private last_active as roTimespan + private request as HttpRequest + private response as HttpResponse + private header_only as boolean + private client as string function new(server as HttpServer, settings as HttpSettings) m.server = server @@ -36,24 +44,23 @@ namespace Http ' re-initializes members for next request-response m.last_active = CreateObject("roTimespan") m.request = new HttpRequest() - m.header = invalid m.response = invalid m.header_only = false m.close = true m.ws_upgrade = false - m.SetState(Http.HttpConnectionState.INIT) + m.SetState(HttpConnectionState.INIT) end function function Recycle() LogDebug("recycle") m.Restart() - m.SetState(Http.HttpConnectionState.RECV_REQUEST) ' ready for another + m.SetState(HttpConnectionState.RECV_REQUEST) ' ready for another end function function Accepted(server as HttpServer, socket as object) m.socket = socket m.id = socket.getID().ToStr() - m.SetState(Http.HttpConnectionState.RECV_REQUEST) + m.SetState(HttpConnectionState.RECV_REQUEST) m.client = m.socket.getReceivedFromAddress().getAddress() LogInfo("accepted connection @" + m.client) @@ -64,7 +71,7 @@ namespace Http end function function PollRequest(server as HttpServer) - if m.state <> Http.HttpConnectionState.RECV_REQUEST + if m.state <> HttpConnectionState.RECV_REQUEST LogError("illegal request state @" + m.client) end if @@ -84,32 +91,32 @@ namespace Http m.request.Add(rcvStr, maybeUnicode) if m.request.ProcessNext(m) - if m.request.state = Http.HttpRequestState.DONE + if m.request.state = HttpRequestState.DONE server.num_requests = validint(server.num_requests) + 1 m.response = new HttpResponse(m.request, m.server, m.settings) m.response.Process(m) - m.SetState(Http.HttpConnectionState.SEND_HEADER) + m.SetState(HttpConnectionState.SEND_HEADER) else - m.setState(Http.HttpConnectionState.DONE) + m.setState(HttpConnectionState.DONE) m.close = true LogError("couldn't process request or response, closing @" + m.client) end if else if m.request.buffer.len() > m.settings.MaxRequestLength ' die if it's too long m.response = new HttpResponse(m.request, m.server, m.settings) m.response.Default(413, "Your request was dropped because it was too long.") - m.SetState(Http.HttpConnectionState.SEND_HEADER) + m.SetState(HttpConnectionState.SEND_HEADER) end if ' if we've moved on to the next state, try to send right away, instead of ' going through another iteration of the poll loop. ' - if m.state = Http.HttpConnectionState.SEND_HEADER + if m.state = HttpConnectionState.SEND_HEADER m.PollHeader(server) end if end function function PollHeader(server as HttpServer) as void - if m.state <> Http.HttpConnectionState.SEND_HEADER + if m.state <> HttpConnectionState.SEND_HEADER LogError("illegal header state @" + m.client) end if @@ -122,16 +129,16 @@ namespace Http if m.response.DoneHeader() if m.response.header_only - m.SetState(Http.HttpConnectionState.DONE) + m.SetState(HttpConnectionState.DONE) else - m.SetState(Http.HttpConnectionState.SEND_RESPONSE) + m.SetState(HttpConnectionState.SEND_RESPONSE) m.PollResponse(server) end if end if end function function PollResponse(server as HttpServer) - if m.state <> Http.HttpConnectionState.SEND_RESPONSE or m.response.header_only + if m.state <> HttpConnectionState.SEND_RESPONSE or m.response.header_only LogError("illegal response state @" + m.client) end if @@ -142,14 +149,14 @@ namespace Http end if if m.response.Done() - m.SetState(Http.HttpConnectionState.DONE) + m.SetState(HttpConnectionState.DONE) end if end function function CheckTimeout(timeoutInMs as integer) if m.last_active.TotalMilliseconds() > timeoutInMs m.close = true - m.SetState(Http.HttpConnectionState.DONE) + m.SetState(HttpConnectionState.DONE) end if end function @@ -167,12 +174,12 @@ namespace Http LogError(op + " transfer error @" + m.client, m.socket.status()) end if m.close = true - m.SetState(Http.HttpConnectionState.DONE) + m.SetState(HttpConnectionState.DONE) end if return gotSome end function - function SetState(newState as Http.HttpConnectionState) + function SetState(newState as HttpConnectionState) if m.state <> newState ' LogDebug("state change" + Stri(m.state) + " ->" + Stri(newState)) m.state = newState diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpRequest.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpRequest.bs index 8a4c750ac..8c3e71b7d 100644 --- a/playlet-lib/src/components/Web/WebServer/Http/HttpRequest.bs +++ b/playlet-lib/src/components/Web/WebServer/Http/HttpRequest.bs @@ -12,20 +12,21 @@ namespace Http class HttpRequest ' members - private method = invalid - private uri = invalid - private route = invalid + public method = invalid + public uri = invalid + public route = invalid private query = invalid private protocol = invalid private encoder = invalid - private buffer = invalid + public buffer = invalid private buffer_index = 0 private headers = invalid private body = invalid - private state = Http.HttpRequestState.INIT + public state = HttpRequestState.INIT as HttpRequestState private id = 0 ' copied members private ready_for_response = false + private maybe_unicode as boolean function new() m.id = Http.GetHttpRequestId() @@ -42,18 +43,18 @@ namespace Http end function function ProcessNext(connection as HttpConnection) as boolean - if m.state = Http.HttpRequestState.DONE + if m.state = HttpRequestState.DONE return m.ready_for_response end if - if m.state = Http.HttpRequestState.INIT - m.state = Http.HttpRequestState.READING_OPERATION + if m.state = HttpRequestState.INIT + m.state = HttpRequestState.READING_OPERATION end if - if m.state = Http.HttpRequestState.READING_OPERATION + if m.state = HttpRequestState.READING_OPERATION if m.ParseOperation() m.ProcessOperation() - m.state = Http.HttpRequestState.READING_HEADERS + m.state = HttpRequestState.READING_HEADERS end if end if diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs index f0e920de4..184294d24 100644 --- a/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs +++ b/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs @@ -10,24 +10,25 @@ namespace Http class HttpServer ' members - private connections = invalid - private sockin = invalid - private uptime = invalid + private connections as roAssociativeArray + private sockin as roStreamSocket + private uptime as roTimespan ' initializable (copied) members - private num_requests = 0 - private total_in = 0 - private total_out = 0 + public num_requests = 0 + public total_in = 0 + public total_out = 0 - private routers - private postRouters + private routers as HttpRouter[] + private postRouters as HttpRouter[] + private utils as Utils public success as boolean public settings as Http.HttpSettings - public task as object + public task as roSGNodePlayletWebServer public websocket as Web.WebSocketServer - function new(settings as HttpSettings, task as object) + function new(settings as HttpSettings, task as roSGNodePlayletWebServer) m.settings = settings m.task = task m.routers = [] @@ -50,6 +51,8 @@ namespace Http end if ' reuse address + ' TODO:P2 remove once fixed + ' bs:disable-next-line 1140 if not sockin.setReuseAddr(true) success = false LogError("setsockopt(SO_REUSEADDR)", sockin.status()) @@ -93,7 +96,7 @@ namespace Http function PreWait() connections = m.connections for each id in connections - conn = connections[id] + conn = connections[id] as HttpConnection conn.CheckTimeout(m.settings.TimeoutInMs) cs = conn.state if cs = Http.HttpConnectionState.DONE @@ -118,13 +121,13 @@ namespace Http function PostWait() connections = m.connections if m.sockin.isReadable() - conn = m.AcceptHttpConnection() + conn = m.AcceptHttpConnection() as HttpConnection if conn <> invalid connections[conn.id] = conn end if end if for each id in connections - conn = connections[id] + conn = connections[id] as HttpConnection cs = conn.state if cs = Http.HttpConnectionState.RECV_REQUEST if conn.socket.isReadable() diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpSettings.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpSettings.bs index cac066f7a..d30811d9c 100644 --- a/playlet-lib/src/components/Web/WebServer/Http/HttpSettings.bs +++ b/playlet-lib/src/components/Web/WebServer/Http/HttpSettings.bs @@ -10,9 +10,9 @@ namespace Http public TimeoutInMs = 60 * 1000 public WebSocketsEnabled = true - public MessagePort = invalid + public MessagePort = invalid as roMessagePort - function new(messagePort as object) + function new(messagePort as roMessagePort) m.MessagePort = messagePort end function diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpUtils.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpUtils.bs index 7c1748f27..5be145ceb 100644 --- a/playlet-lib/src/components/Web/WebServer/Http/HttpUtils.bs +++ b/playlet-lib/src/components/Web/WebServer/Http/HttpUtils.bs @@ -3,11 +3,14 @@ import "pkg:/source/utils/Types.bs" namespace Http class Utils + private mimeTypes as object + private httpCodesMap as object + function MimeType(uri = "" as string) as string - map = m.MimeTypes + map = m.mimeTypes if map = invalid map = ParseJson(ReadAsciiFile("libpkg:/config/mime-types.json5")) - m.MimeTypes = map + m.mimeTypes = map end if ext = m.GetExtension(uri) if map.doesexist(ext) diff --git a/playlet-lib/src/components/Web/WebServer/Middleware/EtagMiddleware.bs b/playlet-lib/src/components/Web/WebServer/Middleware/EtagMiddleware.bs index edc4d5639..b021f5e66 100644 --- a/playlet-lib/src/components/Web/WebServer/Middleware/EtagMiddleware.bs +++ b/playlet-lib/src/components/Web/WebServer/Middleware/EtagMiddleware.bs @@ -7,6 +7,8 @@ namespace Http class EtagMiddleware extends HttpRouter + private etags as EtagUtils + function new(etags as EtagUtils) super() diff --git a/playlet-lib/src/components/Web/WebServer/Middleware/EtagUtils.bs b/playlet-lib/src/components/Web/WebServer/Middleware/EtagUtils.bs index 28a743aeb..62f1c0f9e 100644 --- a/playlet-lib/src/components/Web/WebServer/Middleware/EtagUtils.bs +++ b/playlet-lib/src/components/Web/WebServer/Middleware/EtagUtils.bs @@ -1,6 +1,9 @@ namespace Http class EtagUtils + + private pathToEtags as object + function new() m.pathToEtags = {} end function diff --git a/playlet-lib/src/components/Web/WebServer/Middleware/HttpStaticFilesRouter.bs b/playlet-lib/src/components/Web/WebServer/Middleware/HttpStaticFilesRouter.bs index a91ce0a24..506d471f0 100644 --- a/playlet-lib/src/components/Web/WebServer/Middleware/HttpStaticFilesRouter.bs +++ b/playlet-lib/src/components/Web/WebServer/Middleware/HttpStaticFilesRouter.bs @@ -3,16 +3,16 @@ import "pkg:/source/utils/StringUtils.bs" namespace Http class HttpStaticFilesRouter extends HttpRouter - private root - private route - private etags + private root as string + private route as string + private etags as EtagUtils - private showDirectories - private showHidden - private fsCheck - private staticFiles + private showDirectories as boolean + private showHidden as boolean + private fsCheck as boolean + private staticFiles as boolean - function new(route as string, root as string, etags as object, options = {} as object) + function new(route as string, root as string, etags as EtagUtils, options = {} as object) super() m.root = root @@ -79,12 +79,14 @@ namespace Http if not path.isValid() ' Skip, let next middleware handle it return false - else if not fs.exists(path) + end if + + if not fs.exists(full_path) ' Skip, let next middleware handle it return false end if - stat = fs.stat(path) + stat = fs.stat(full_path) if stat = invalid response.Default(500, "fstat() failed.") return true @@ -96,7 +98,7 @@ namespace Http return true end if response.ContentType("text/html") - m.GenerateDirectoryListing(path, request, response) + m.GenerateDirectoryListing(full_path, request, response) if m.staticFiles m.etags.AddEtagFromBody(request, response, full_path) end if @@ -104,9 +106,9 @@ namespace Http else if stat.type = "file" mimetype = server.utils.MimeType(decoded_path) response.ContentType(mimetype) - response.SetBodyDataFile(path) + response.SetBodyDataFile(full_path) response.http_code = 200 - LogInfo("uri:", request.uri, "target:", path, "content-type:", mimetype, "content-length", stat.size) + LogInfo("uri:", request.uri, "target:", full_path, "content-type:", mimetype, "content-length", stat.size) if m.staticFiles m.etags.AddEtagFromBody(request, response, full_path) end if @@ -117,7 +119,7 @@ namespace Http end if end function - function GenerateDirectoryListing(path as object, request as HttpRequest, response as HttpResponse) as boolean + function GenerateDirectoryListing(path as string, request as HttpRequest, response as HttpResponse) as boolean fs = CreateObject("roFilesystem") dirList = fs.GetDirectoryListing(path) if dirList = invalid @@ -142,7 +144,7 @@ namespace Http

${request.uri.DecodeUri()}

\n`
 
-            dir = path.getString()
+            dir = path
             if dir.len() > 0 and dir.right(1) <> "/"
                 dir = dir + "/"
             end if
diff --git a/playlet-lib/src/components/Web/WebServer/WebServer.bs b/playlet-lib/src/components/Web/WebServer/WebServer.bs
index 3e38f15ba..60c7061b1 100644
--- a/playlet-lib/src/components/Web/WebServer/WebServer.bs
+++ b/playlet-lib/src/components/Web/WebServer/WebServer.bs
@@ -6,7 +6,7 @@ function Init()
     m.top.functionName = "WebServerLoop"
 end function
 
-function StartServer(_unused as dynamic) as boolean
+function StartServer() as boolean
     if m.top.isRunning = true
         return true
     end if
@@ -15,7 +15,7 @@ function StartServer(_unused as dynamic) as boolean
     return true
 end function
 
-function StopServer(_unused as dynamic) as void
+function StopServer() as void
     if m.top.isRunning = false
         return
     end if
diff --git a/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketConnection.bs b/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketConnection.bs
index c360b046b..52aa20f63 100644
--- a/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketConnection.bs
+++ b/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketConnection.bs
@@ -7,11 +7,13 @@ namespace Web
     const BUFSIZE = 524288
 
     class WebSocketConnection
+        public id = invalid
+        public state = invalid
+
         private server
         private socket
         private frame
-        public id = invalid
-        public state = invalid
+        private buffer
 
         function new(server as WebSocketServer, socket as object)
             m.server = server
diff --git a/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketFrame.bs b/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketFrame.bs
index 79fc72c11..51c68f53e 100644
--- a/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketFrame.bs
+++ b/playlet-lib/src/components/Web/WebServer/WebSockets/WebSocketFrame.bs
@@ -13,6 +13,7 @@ namespace Web
 
         private index
         private length
+        private buffer
 
         function new()
             m.payload = CreateObject("roByteArray")
diff --git a/playlet-lib/src/components/parts/AutoBind/AutoBind.part.bs b/playlet-lib/src/components/parts/AutoBind/AutoBind.part.bs
index 51176e34a..6c2a4088d 100644
--- a/playlet-lib/src/components/parts/AutoBind/AutoBind.part.bs
+++ b/playlet-lib/src/components/parts/AutoBind/AutoBind.part.bs
@@ -25,7 +25,7 @@ function AutoBindSceneGraph() as void
 end function
 
 ' Bind the node fields, to be called with interface function
-function BindNodeFieldsAndProps(_unused as dynamic) as void
+function BindNodeFieldsAndProps() as void
     node = m.top
     bindings = node.bindings
     if bindings = invalid
@@ -67,7 +67,7 @@ end function
 
 ' Create scoped fields (m.fieldName) for all fields in this node
 ' To be called after BindNodeFieldsAndProps
-function BindScopeFields(_unused as dynamic)
+function BindScopeFields()
     types = m.top.getFieldTypes()
     for each key in types
         if m.DoesExist(key)
@@ -84,10 +84,10 @@ function BindScopeFields(_unused as dynamic)
 end function
 
 ' Bind a single node. This for nodes created dynamically, and all its dependencies are expected to be bound already
-function BindNode(_unused as dynamic)
+function BindNode()
     RemoveNodeFromGlobalAutoBind()
-    BindNodeFieldsAndProps(invalid)
-    BindScopeFields(invalid)
+    BindNodeFieldsAndProps()
+    BindScopeFields()
     m.top.binding_done = true
 end function
 

From cc5e3a96ba05567290892dc58e287b9042b414ad Mon Sep 17 00:00:00 2001
From: Brahim Hadriche 
Date: Wed, 24 Jul 2024 21:25:10 -0400
Subject: [PATCH 22/25] Final touches

---
 .../Services/LoungeService/LongPoller.bs      |  2 +
 .../PlayletWebServer/Middleware/DialRouter.bs |  8 ++
 .../Middleware/RegistryRouter.bs              | 75 ++++++++++---------
 .../Web/WebServer/Http/HttpResponse.bs        | 14 +++-
 .../Web/WebServer/Http/HttpRouter.bs          |  4 +-
 .../Web/WebServer/Http/HttpServer.bs          |  6 +-
 playlet-lib/src/source/services/HttpClient.bs |  2 +
 7 files changed, 65 insertions(+), 46 deletions(-)

diff --git a/playlet-lib/src/components/Services/LoungeService/LongPoller.bs b/playlet-lib/src/components/Services/LoungeService/LongPoller.bs
index 060cd4ed7..02162285a 100644
--- a/playlet-lib/src/components/Services/LoungeService/LongPoller.bs
+++ b/playlet-lib/src/components/Services/LoungeService/LongPoller.bs
@@ -72,6 +72,8 @@ class LongPoller
     '   - false if we're no longer returning data - socket is closed
     '   - true if we're still waiting for data
     '   - array we've received chunk(s) of data
+    ' TODO:P0 remove invalid attribute
+    @invalid
     function Poll(socketMessages as object) as dynamic
         if m.socket = invalid
             return false
diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs
index ce3606bca..615bf9245 100644
--- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs
+++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/DialRouter.bs
@@ -32,6 +32,8 @@ namespace Http
         end function
 
         ' @get("/dial/:device-id/device-description.xml")
+        ' TODO:P0 remove invalid attribute
+        @invalid
         function GetDialManifest(context as object) as boolean
             response = context.response
 
@@ -45,6 +47,8 @@ namespace Http
         end function
 
         ' @get("/dial/:device-id/YouTube")
+        ' TODO:P0 remove invalid attribute
+        @invalid
         function GetDialYouTube(context as object) as boolean
             response = context.response
 
@@ -58,6 +62,8 @@ namespace Http
         end function
 
         ' @post("/dial/:device-id/YouTube")
+        ' TODO:P0 remove invalid attribute
+        @invalid
         function PostDialYouTube(context as object) as boolean
             request = context.request
             response = context.response
@@ -109,6 +115,8 @@ namespace Http
         end function
 
         ' @delete("/dial/:device-id/YouTube/run")
+        ' TODO:P0 remove invalid attribute
+        @invalid
         function CloseChannel(context as object) as boolean
             response = context.response
 
diff --git a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/RegistryRouter.bs b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/RegistryRouter.bs
index 4d61473ab..26cdec73b 100644
--- a/playlet-lib/src/components/Web/PlayletWebServer/Middleware/RegistryRouter.bs
+++ b/playlet-lib/src/components/Web/PlayletWebServer/Middleware/RegistryRouter.bs
@@ -1,49 +1,50 @@
-#if DEBUG
-    import "pkg:/source/utils/RegistryUtils.bs"
+' TODO:P0 restore
+' #if DEBUG
+import "pkg:/source/utils/RegistryUtils.bs"
 
-    namespace Http
+namespace Http
 
-        class RegistryRouter extends HttpRouter
+    class RegistryRouter extends HttpRouter
 
-            function new()
-                super()
-            end function
+        function new()
+            super()
+        end function
 
-            @get("/debug/registry")
-            function GetRegistry(context as object) as boolean
-                response = context.response
+        @get("/debug/registry")
+        function GetRegistry(context as object) as boolean
+            response = context.response
 
-                registryValues = RegistryUtils.ReadAll()
-                response.Json(registryValues)
-                return true
-            end function
-
-            @post("/debug/registry")
-            function SetRegistry(context as object) as boolean
-                request = context.request
-                response = context.response
+            registryValues = RegistryUtils.ReadAll()
+            response.Json(registryValues)
+            return true
+        end function
 
-                payload = request.Json()
-                if payload = invalid
-                    response.Default(400, "Invalid JSON")
-                    return true
-                end if
+        @post("/debug/registry")
+        function SetRegistry(context as object) as boolean
+            request = context.request
+            response = context.response
 
-                RegistryUtils.WriteAll(payload)
-                response.Default(204, "OK")
+            payload = request.Json()
+            if payload = invalid
+                response.Default(400, "Invalid JSON")
                 return true
-            end function
+            end if
 
-            @delete("/debug/registry")
-            function ClearRegistry(context as object) as boolean
-                response = context.response
+            RegistryUtils.WriteAll(payload)
+            response.Default(204, "OK")
+            return true
+        end function
 
-                RegistryUtils.DeleteAll()
-                response.Default(204, "OK")
-                return true
-            end function
+        @delete("/debug/registry")
+        function ClearRegistry(context as object) as boolean
+            response = context.response
+
+            RegistryUtils.DeleteAll()
+            response.Default(204, "OK")
+            return true
+        end function
 
-        end class
+    end class
 
-    end namespace
-#end if
+end namespace
+' endif
diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpResponse.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpResponse.bs
index db5ec4a35..08b8eabb8 100644
--- a/playlet-lib/src/components/Web/WebServer/Http/HttpResponse.bs
+++ b/playlet-lib/src/components/Web/WebServer/Http/HttpResponse.bs
@@ -8,6 +8,8 @@ namespace Http
     end function
 
     class HttpResponse
+        public server as HttpServer
+
         ' members
         private body_buffer = invalid
         private header_buffer = invalid
@@ -19,12 +21,16 @@ namespace Http
         private body_buffer_length = 0
         private sent = 0
         private header_sent = 0
-        private header_only = false
+        public header_only = false
         private buf_start = 0
-        private http_code = 0
+        public http_code = 0
+
+        public settings
 
-        private server
-        private settings
+        private _now as string
+        private headers as object
+        private header as string
+        private header_length as integer
 
         function new(request as HttpRequest, server as HttpServer, settings as HttpSettings)
             m.id = Http.GetHttpResponseId()
diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpRouter.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpRouter.bs
index 2197545d5..66edfd129 100644
--- a/playlet-lib/src/components/Web/WebServer/Http/HttpRouter.bs
+++ b/playlet-lib/src/components/Web/WebServer/Http/HttpRouter.bs
@@ -8,13 +8,13 @@ namespace Http
         '     router: router as HttpRouter
         '     func: func as string
         ' }]
-        private routes
+        public routes
 
         function new()
             m.routes = []
         end function
 
-        private function OnRequest(request as object, response as HttpResponse, connection as HttpConnection) as boolean
+        function OnRequest(request as object, response as HttpResponse, connection as HttpConnection) as boolean
             for each route in m.routes
                 if m.RouteMatchesRequest(route, request)
                     try
diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs
index 184294d24..8d8ad6b38 100644
--- a/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs
+++ b/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs
@@ -19,9 +19,9 @@ namespace Http
         public total_in = 0
         public total_out = 0
 
-        private routers as HttpRouter[]
-        private postRouters as HttpRouter[]
-        private utils as Utils
+        public routers as HttpRouter[]
+        public postRouters as HttpRouter[]
+        public utils as Utils
 
         public success as boolean
         public settings as Http.HttpSettings
diff --git a/playlet-lib/src/source/services/HttpClient.bs b/playlet-lib/src/source/services/HttpClient.bs
index c0b779cbc..6e990995d 100644
--- a/playlet-lib/src/source/services/HttpClient.bs
+++ b/playlet-lib/src/source/services/HttpClient.bs
@@ -319,6 +319,8 @@ namespace HttpClient
 
         ' Note: Calling Send() only without Await() will not guarentee a request will be sent.
         ' If a Task finishes before the request is sent, the request might be dropped.
+        ' TODO:P0 remove invalid attribute
+        @invalid
         function Send() as HttpRequest
             if m.urlTransfer <> invalid or m._cache <> invalid
                 return m

From 7fe13ca44058a1a05e3bb837024e472b0bdb035d Mon Sep 17 00:00:00 2001
From: Brahim Hadriche 
Date: Wed, 24 Jul 2024 22:20:29 -0400
Subject: [PATCH 23/25] Roku types plugin

---
 config/bsconfig.base.jsonc                    |  1 +
 config/bsconfig.tests.base.jsonc              |  1 +
 docs/plugins.md                               | 13 ++++++
 playlet-app/src/source/Main.bs                |  2 -
 playlet-lib/src/components/Logger/Logger.bs   |  2 -
 .../Web/WebServer/Http/HttpServer.bs          |  2 -
 tools/bs-plugins/roku-types-plugin.ts         | 45 +++++++++++++++++++
 7 files changed, 60 insertions(+), 6 deletions(-)
 create mode 100644 tools/bs-plugins/roku-types-plugin.ts

diff --git a/config/bsconfig.base.jsonc b/config/bsconfig.base.jsonc
index a35ca8de4..4d151e9df 100644
--- a/config/bsconfig.base.jsonc
+++ b/config/bsconfig.base.jsonc
@@ -75,6 +75,7 @@
     "lintConfig": "./config/bslint.jsonc",
     "plugins": [
         "@rokucommunity/bslint",
+        "../tools/bs-plugins/roku-types-plugin.ts",
         "../tools/bs-plugins/asynctask-plugin.ts",
         "../tools/bs-plugins/manifest-edit-plugin.ts",
         "../tools/bs-plugins/component-includes-plugin.ts",
diff --git a/config/bsconfig.tests.base.jsonc b/config/bsconfig.tests.base.jsonc
index 06bda329e..9b80a4d15 100644
--- a/config/bsconfig.tests.base.jsonc
+++ b/config/bsconfig.tests.base.jsonc
@@ -19,6 +19,7 @@
     "plugins": [
         "@rokucommunity/bslint",
         "rooibos-roku",
+        "../tools/bs-plugins/roku-types-plugin.ts",
         "../tools/bs-plugins/asynctask-plugin.ts",
         "../tools/bs-plugins/manifest-edit-plugin.ts",
         "../tools/bs-plugins/component-includes-plugin.ts",
diff --git a/docs/plugins.md b/docs/plugins.md
index d09daadec..9a8079fca 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -13,6 +13,7 @@
 - [Type Gen](#type-gen)
 - [Web Server](#web-server)
 - [Locale validation](#locale-validation)
+- [Roku types](#roku-types)
 
 Playlet implements a few [Brighterscript Plugins](https://github.com/rokucommunity/brighterscript/blob/master/docs/plugins.md). The plugins inject themselves in the compilation process, allowing the modification of bs scripts, xml components, and even assets or the app manifest. Let's start with a simple one:
 
@@ -623,3 +624,15 @@ The plugin checks for the following:
 - `en_US` must have matching source and translation values, so it can act as a fallback translation.
 - All `source` translations from all languages must be present in the `@locale` enums. This is to prevent renaming the values in the code without updating translation files.
 - Translation `source` keys can't be used except for certain fields such as `"text"` and `"title"`. This is to prevent the accidental localization of non-display fields, such as node ids.
+
+## Roku types
+
+**[Source](/tools/bs-plugins/roku-types-plugin.ts)**
+
+### Why
+
+BrighterScript compiler contains a list of Roku types scraped from the documentation website. Sometimes documentation is not perfect, which causes false positives in validaiton. This plugin allows to patch the data types.
+
+### How
+
+We check if components/interfaces are linked correctly, and if not, override them. This is possible because the Roku types used by bsc are exported, and we're able to patch them before the program starts in the `beforeProgramCreate` hook. This is important because Roku types are populated on program creation.
diff --git a/playlet-app/src/source/Main.bs b/playlet-app/src/source/Main.bs
index 56d20175f..756feea34 100644
--- a/playlet-app/src/source/Main.bs
+++ b/playlet-app/src/source/Main.bs
@@ -49,8 +49,6 @@ function Main(args as object) as void
     input.setMessagePort(port)
 
     systemLog = CreateObject("roSystemLog")
-    ' TODO:P2 remove after fix
-    ' bs:disable-next-line 1140
     systemLog.SetMessagePort(port)
     ' Although all types are enabled, they are filtered in Playlet Lib to avoid spamming the logs
     systemLog.EnableType("http.connect")
diff --git a/playlet-lib/src/components/Logger/Logger.bs b/playlet-lib/src/components/Logger/Logger.bs
index 8f7e494e2..27659ea43 100644
--- a/playlet-lib/src/components/Logger/Logger.bs
+++ b/playlet-lib/src/components/Logger/Logger.bs
@@ -55,8 +55,6 @@ function LoggerLoop()
 
     appMemoryMonitor = CreateObject("roAppMemoryMonitor")
     if appMemoryMonitor <> invalid and FindMemberFunction(appMemoryMonitor, "EnableMemoryWarningEvent") <> invalid
-        ' TODO:P2 remove after fix
-        ' bs:disable-next-line 1140
         appMemoryMonitor.SetMessagePort(port)
         appMemoryMonitor.EnableMemoryWarningEvent(true)
     end if
diff --git a/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs b/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs
index 8d8ad6b38..61e001b6d 100644
--- a/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs
+++ b/playlet-lib/src/components/Web/WebServer/Http/HttpServer.bs
@@ -51,8 +51,6 @@ namespace Http
             end if
 
             ' reuse address
-            ' TODO:P2 remove once fixed
-            ' bs:disable-next-line 1140
             if not sockin.setReuseAddr(true)
                 success = false
                 LogError("setsockopt(SO_REUSEADDR)", sockin.status())
diff --git a/tools/bs-plugins/roku-types-plugin.ts b/tools/bs-plugins/roku-types-plugin.ts
new file mode 100644
index 000000000..02d467ba0
--- /dev/null
+++ b/tools/bs-plugins/roku-types-plugin.ts
@@ -0,0 +1,45 @@
+// This plugin overrides Roku data types used by validation and completion features
+
+import {
+    BeforeProgramCreateEvent,
+    CompilerPlugin,
+} from 'brighterscript';
+
+import { components } from 'brighterscript/dist/roku-types/index';
+
+export class RokuTypesPlugin implements CompilerPlugin {
+    public name = 'RokuTypesPlugin';
+
+    beforeProgramCreate(event: BeforeProgramCreateEvent) {
+        if (components.roappmemorymonitor.interfaces.find(i => i.name === 'ifSetMessagePort')) {
+            event.builder.logger.error('ifSetMessagePort already exists on roAppMemoryMonitor');
+        } else {
+            components.roappmemorymonitor.interfaces.push({
+                "name": "ifSetMessagePort",
+                "url": "https://developer.roku.com/docs/references/brightscript/interfaces/ifsetmessageport.md"
+            });
+        }
+
+        if (components.rosystemlog.interfaces.find(i => i.name === 'ifSetMessagePort')) {
+            event.builder.logger.error('ifSetMessagePort already exists on roSystemLog');
+        } else {
+            components.rosystemlog.interfaces.push({
+                "name": "ifSetMessagePort",
+                "url": "https://developer.roku.com/docs/references/brightscript/interfaces/ifsetmessageport.md"
+            });
+        }
+
+        if (components.rostreamsocket.interfaces.find(i => i.name === 'ifSocketOption')) {
+            event.builder.logger.error('ifSocketOption already exists on roStreamSocket');
+        } else {
+            components.rostreamsocket.interfaces.push({
+                "name": "ifSocketOption",
+                "url": "https://developer.roku.com/docs/references/brightscript/interfaces/ifsocketoption.md"
+            });
+        }
+    }
+}
+
+export default () => {
+    return new RokuTypesPlugin();
+};

From 1fe39dba666cd2de502872cdb13f4cb6c40ac885 Mon Sep 17 00:00:00 2001
From: Brahim Hadriche 
Date: Wed, 24 Jul 2024 22:35:56 -0400
Subject: [PATCH 24/25] Small cleanups

---
 .../components/BootstrapScene/BootstrapScene.bs  |  2 +-
 .../Services/ApplicationInfo/ApplicationInfo.bs  | 16 ++++++++--------
 .../Services/LoungeService/LoungeApi.bs          |  1 -
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/playlet-app/src/components/BootstrapScene/BootstrapScene.bs b/playlet-app/src/components/BootstrapScene/BootstrapScene.bs
index 7a2025dec..a22fade3e 100644
--- a/playlet-app/src/components/BootstrapScene/BootstrapScene.bs
+++ b/playlet-app/src/components/BootstrapScene/BootstrapScene.bs
@@ -20,7 +20,7 @@ function Init() as void
     LoadPlayletLib()
 end function
 
-' TODO:P2 remove after fix
+' TODO:P0 remove after fix
 ' bs:disable-next-line LINT2004
 function GetPlayletLibUrls() as object
     #if DEBUG
diff --git a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs
index 02b20344f..c91845844 100644
--- a/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs
+++ b/playlet-lib/src/components/Services/ApplicationInfo/ApplicationInfo.bs
@@ -39,14 +39,14 @@ function GetLatestPlayletLibVersion() as dynamic
         return invalid
     end if
 
-    m.latestLibVersionTask = AsyncTask.Start(Tasks.LatestLibVersionTask, {}, OnLatestLibVersionTaskResult)
+    ' TODO:P2 remove after fix
+    ' bs:disable-next-line LINT1001
+    m.latestLibVersionTask = AsyncTask.Start(Tasks.LatestLibVersionTask, {}, function(output as object) as void
+        m.latestLibVersionTask = invalid
+        if output.success and output.result.latest <> invalid
+            m.top.lib_version_latest = output.result.latest
+        end if
+    end function)
 
     return invalid
 end function
-
-function OnLatestLibVersionTaskResult(output as object) as void
-    m.latestLibVersionTask = invalid
-    if output.success and output.result.latest <> invalid
-        m.top.lib_version_latest = output.result.latest
-    end if
-end function
diff --git a/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs b/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs
index d7084dada..b23de23b8 100644
--- a/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs
+++ b/playlet-lib/src/components/Services/LoungeService/LoungeApi.bs
@@ -544,7 +544,6 @@ class LoungeApi
         end for
 
         loungeData = FormatJson(loungeData)
-        ' TODO:P0 check if this is valid usage
         RegistryUtils.Write(RegistryUtils.LAST_LOUNGE_DATA, loungeData as string)
     end function
 

From 6f095ed7ba8d2f0dacc430520ae5a39ff0627b57 Mon Sep 17 00:00:00 2001
From: Brahim Hadriche 
Date: Wed, 24 Jul 2024 22:41:13 -0400
Subject: [PATCH 25/25] Update transpiled files

---
 .../src/components/MainScene.transpiled.brs   |  6 ++--
 .../src/components/MainScene.transpiled.xml   | 36 +++++++++----------
 .../MainScene_bindings.transpiled.brs         |  1 -
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/playlet-lib/src/components/MainScene.transpiled.brs b/playlet-lib/src/components/MainScene.transpiled.brs
index 3cf9c0f92..1573ae953 100644
--- a/playlet-lib/src/components/MainScene.transpiled.brs
+++ b/playlet-lib/src/components/MainScene.transpiled.brs
@@ -23,10 +23,10 @@ end function
 
 function StartWebServer()
     m.loungeService = m.top.findNode("LoungeService")
-    m.loungeService.callfunc("StartService", invalid)
+    m.loungeService.callfunc("StartService")
     m.webServer = m.top.findNode("WebServer")
-    m.webServer.callfunc("StartServer", invalid)
+    m.webServer.callfunc("StartServer")
     m.dialServer = m.top.findNode("DialServer")
-    m.dialServer.callfunc("StartServer", invalid)
+    m.dialServer.callfunc("StartServer")
 end function
 '//# sourceMappingURL=./MainScene.brs.map
\ No newline at end of file
diff --git a/playlet-lib/src/components/MainScene.transpiled.xml b/playlet-lib/src/components/MainScene.transpiled.xml
index 13863f92b..f8593c14e 100644
--- a/playlet-lib/src/components/MainScene.transpiled.xml
+++ b/playlet-lib/src/components/MainScene.transpiled.xml
@@ -1,22 +1,4 @@
 
-    
-        
-        
-        
-        
-        
-    
-