diff --git a/.lintstagedrc.json b/.lintstagedrc.json index 4e9b31be5..5dcd5926a 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -1,4 +1,5 @@ { "*.js": "eslint --cache", + "*.ts": "eslint --cache", "app/styles/**/*.scss": "stylelint" } diff --git a/app/soapbox/utils/accounts.js b/app/soapbox/utils/accounts.js deleted file mode 100644 index 6970f0050..000000000 --- a/app/soapbox/utils/accounts.js +++ /dev/null @@ -1,69 +0,0 @@ -import { Map as ImmutableMap } from 'immutable'; -import { List as ImmutableList } from 'immutable'; - -const getDomainFromURL = account => { - try { - const url = account.get('url'); - return new URL(url).host; - } catch { - return ''; - } -}; - -export const getDomain = account => { - const domain = account.get('acct').split('@')[1]; - return domain ? domain : getDomainFromURL(account); -}; - -export const guessFqn = account => { - const [user, domain] = account.get('acct').split('@'); - if (!domain) return [user, getDomainFromURL(account)].join('@'); - return account.get('acct'); -}; - -export const getBaseURL = account => { - try { - const url = account.get('url'); - return new URL(url).origin; - } catch { - return ''; - } -}; - -// user@domain even for local users -export const acctFull = account => ( - account.get('fqn') || guessFqn(account) -); - -export const getAcct = (account, displayFqn) => ( - displayFqn === true ? acctFull(account) : account.get('acct') -); - -export const isStaff = (account = ImmutableMap()) => ( - [isAdmin, isModerator].some(f => f(account) === true) -); - -export const isAdmin = account => ( - account.getIn(['pleroma', 'is_admin']) === true -); - -export const isModerator = account => ( - account.getIn(['pleroma', 'is_moderator']) === true -); - -export const getFollowDifference = (state, accountId, type) => { - const listSize = state.getIn(['user_lists', type, accountId, 'items'], ImmutableList()).size; - const counter = state.getIn(['accounts_counters', accountId, `${type}_count`], 0); - return Math.max(counter - listSize, 0); -}; - -export const isLocal = account => { - const domain = account.get('acct').split('@')[1]; - return domain === undefined ? true : false; -}; - -export const isRemote = account => !isLocal(account); - -export const isVerified = account => ( - account.getIn(['pleroma', 'tags'], ImmutableList()).includes('verified') -); diff --git a/app/soapbox/utils/accounts.ts b/app/soapbox/utils/accounts.ts new file mode 100644 index 000000000..e3b7a7a56 --- /dev/null +++ b/app/soapbox/utils/accounts.ts @@ -0,0 +1,73 @@ +import { + Map as ImmutableMap, + List as ImmutableList, + OrderedSet as ImmutableOrderedSet, +} from 'immutable'; + +const getDomainFromURL = (account: ImmutableMap): string => { + try { + const url = account.get('url'); + return new URL(url).host; + } catch { + return ''; + } +}; + +export const getDomain = (account: ImmutableMap): string => { + const domain = account.get('acct').split('@')[1]; + return domain ? domain : getDomainFromURL(account); +}; + +export const guessFqn = (account: ImmutableMap): string => { + const [user, domain] = account.get('acct').split('@'); + if (!domain) return [user, getDomainFromURL(account)].join('@'); + return account.get('acct'); +}; + +export const getBaseURL = (account: ImmutableMap): string => { + try { + const url = account.get('url'); + return new URL(url).origin; + } catch { + return ''; + } +}; + +// user@domain even for local users +export const acctFull = (account: ImmutableMap): string => ( + account.get('fqn') || guessFqn(account) +); + +export const getAcct = (account: ImmutableMap, displayFqn: boolean) :string => ( + displayFqn === true ? acctFull(account) : account.get('acct') +); + +export const isStaff = (account: ImmutableMap = ImmutableMap()): boolean => ( + [isAdmin, isModerator].some(f => f(account) === true) +); + +export const isAdmin = (account: ImmutableMap): boolean => ( + account.getIn(['pleroma', 'is_admin']) === true +); + +export const isModerator = (account: ImmutableMap): boolean => ( + account.getIn(['pleroma', 'is_moderator']) === true +); + +export const getFollowDifference = (state: ImmutableMap, accountId: string, type: string): number => { + const items: any = state.getIn(['user_lists', type, accountId, 'items'], ImmutableOrderedSet()); + const counter: number = Number(state.getIn(['accounts_counters', accountId, `${type}_count`], 0)); + return Math.max(counter - items.size, 0); +}; + +export const isLocal = (account: ImmutableMap): boolean => { + const domain: string = account.get('acct').split('@')[1]; + return domain === undefined ? true : false; +}; + +export const isRemote = (account: ImmutableMap): boolean => !isLocal(account); + +export const isVerified = (account: ImmutableMap): boolean => { + const tags: any = account.getIn(['pleroma', 'tags'], ImmutableList()); + return tags.includes('verified'); +}; diff --git a/package.json b/package.json index 5f4529840..dcb0fd414 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "manage:translations": "node ./webpack/translationRunner.js", "test": "${npm_execpath} run test:lint && ${npm_execpath} run test:jest", "test:lint": "${npm_execpath} run test:lint:js && ${npm_execpath} run test:lint:sass", - "test:lint:js": "npx eslint --ext=js . --cache", + "test:lint:js": "npx eslint --ext .js,.jsx,.ts,.tsx . --cache", "test:lint:sass": "npx stylelint app/styles/**/*.scss", "test:jest": "npx jest --coverage", "prepare": "husky install" @@ -85,6 +85,7 @@ "escape-html": "^1.0.3", "exif-js": "^2.3.0", "feather-icons": "^4.28.0", + "fork-ts-checker-webpack-plugin": "^6.4.0", "html-webpack-harddisk-plugin": "^2.0.0", "html-webpack-plugin": "^5.3.2", "http-link-header": "^1.0.2", @@ -151,9 +152,10 @@ "terser-webpack-plugin": "^5.2.3", "tiny-queue": "^0.2.1", "ts-jest": "^27.0.5", + "ts-loader": "^9.2.6", "tslib": "^2.3.1", "twemoji": "https://github.com/twitter/twemoji#v13.0.2", - "typescript": "^4.0.3", + "typescript": "^4.4.4", "util": "^0.12.4", "uuid": "^8.3.2", "webpack": "^5.52.0", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..41f113e86 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "sourceMap": true, + "noImplicitAny": true, + "module": "es6", + "target": "es5", + "jsx": "react", + "allowJs": true, + "moduleResolution": "node", + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true + } +} diff --git a/webpack/configuration.js b/webpack/configuration.js index 960e25e60..f2cc0c7fb 100644 --- a/webpack/configuration.js +++ b/webpack/configuration.js @@ -12,7 +12,7 @@ const settings = { test_root_path: `${FE_BUILD_DIR}-test`, cache_path: 'tmp/cache', resolved_paths: [], - extensions: [ '.mjs', '.js', '.sass', '.scss', '.css', '.module.sass', '.module.scss', '.module.css', '.png', '.svg', '.gif', '.jpeg', '.jpg' ], + extensions: [ '.mjs', '.js', '.jsx', '.ts', '.tsx', '.sass', '.scss', '.css', '.module.sass', '.module.scss', '.module.css', '.png', '.svg', '.gif', '.jpeg', '.jpg' ], }; const outputDir = env.NODE_ENV === 'test' ? settings.test_root_path : settings.public_root_path; diff --git a/webpack/rules/babel.js b/webpack/rules/babel.js index 2fc245c43..6c40d6d7f 100644 --- a/webpack/rules/babel.js +++ b/webpack/rules/babel.js @@ -2,13 +2,20 @@ const { join, resolve } = require('path'); const { env, settings } = require('../configuration'); module.exports = { - test: /\.(js|jsx|mjs)$/, + test: /\.(js|jsx|mjs|ts|tsx)$/, include: [ settings.source_path, ...settings.resolved_paths, ].map(p => resolve(p)), exclude: /node_modules/, use: [ + { + loader: 'ts-loader', + options: { + // disable type checker - we will use it in fork plugin + transpileOnly: true, + }, + }, { loader: 'babel-loader', options: { diff --git a/webpack/rules/index.js b/webpack/rules/index.js index d3290659e..4c4fa6872 100644 --- a/webpack/rules/index.js +++ b/webpack/rules/index.js @@ -8,7 +8,6 @@ const nodeModules = require('./node_modules'); // Webpack loaders are processed in reverse order // https://webpack.js.org/concepts/loaders/#loader-features -// Lastly, process static files using file loader module.exports = [ ...assets, css, diff --git a/webpack/shared.js b/webpack/shared.js index c7343f005..a5d407111 100644 --- a/webpack/shared.js +++ b/webpack/shared.js @@ -7,6 +7,7 @@ const AssetsManifestPlugin = require('webpack-assets-manifest'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin'); const CopyPlugin = require('copy-webpack-plugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const { env, settings, output } = require('./configuration'); const rules = require('./rules'); @@ -72,6 +73,7 @@ module.exports = { new webpack.ProvidePlugin({ process: 'process/browser', }), + new ForkTsCheckerWebpackPlugin(), new MiniCssExtractPlugin({ filename: 'packs/css/[name]-[contenthash:8].css', chunkFilename: 'packs/css/[name]-[contenthash:8].chunk.css', diff --git a/yarn.lock b/yarn.lock index 53753d04a..a7488578a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,6 +16,13 @@ dependencies: "@babel/highlight" "^7.14.5" +"@babel/code-frame@^7.8.3": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" + integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== + dependencies: + "@babel/highlight" "^7.16.0" + "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" @@ -233,6 +240,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== +"@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" @@ -266,6 +278,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" + integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== + dependencies: + "@babel/helper-validator-identifier" "^7.15.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.5", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2", "@babel/parser@^7.9.4": version "7.15.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549" @@ -1636,7 +1657,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== @@ -1975,12 +1996,12 @@ airbnb-prop-types@^2.16.0: prop-types-exact "^1.2.0" react-is "^16.13.1" -ajv-keywords@^3.5.2: +ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2706,7 +2727,7 @@ cheerio@^1.0.0-rc.10, cheerio@^1.0.0-rc.3: parse5-htmlparser2-tree-adapter "^6.0.1" tslib "^2.2.0" -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.2, chokidar@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== @@ -3631,6 +3652,14 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +enhanced-resolve@^5.0.0: + version "5.8.3" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" + integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + enhanced-resolve@^5.8.0: version "5.8.2" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b" @@ -4296,6 +4325,25 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +fork-ts-checker-webpack-plugin@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.4.0.tgz#057e477cf1d8b013b2ed2669437f818680289c4c" + integrity sha512-3I3wFkc4DbzaUDPWEi96wdYGu4EKtxBafhZYm0o4mX51d9bphAY4P3mBl8K5mFXFJqVzHfmdbm9kLGnm7vwwBg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@types/json-schema" "^7.0.5" + chalk "^4.1.0" + chokidar "^3.4.2" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + glob "^7.1.6" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "2.7.0" + semver "^7.3.2" + tapable "^1.0.0" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -4457,6 +4505,18 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.6: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-modules@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" @@ -6424,6 +6484,13 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= +memfs@^3.1.2: + version "3.3.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" + integrity sha512-BEE62uMfKOavX3iG7GYX43QJ+hAeeWnwIAuJ/R6q96jaMtiLzhsxHJC8B1L7fK7Pt/vXDRwb3SG/yBpNGDPqzg== + dependencies: + fs-monkey "1.0.3" + memfs@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.2.4.tgz#1108c28d2e9137daf5a5586af856c3e18c1c64b2" @@ -6477,7 +6544,7 @@ micromark@~2.11.0: debug "^4.0.0" parse-entities "^2.0.0" -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -8519,6 +8586,15 @@ schema-utils@*, schema-utils@^3.0, schema-utils@^3.0.0, schema-utils@^3.1.0, sch ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== + dependencies: + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" + schema-utils@^2.6.5, schema-utils@^2.6.6: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" @@ -9195,6 +9271,11 @@ taffydb@2.6.2: resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg= +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + tapable@^2.0, tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -9369,6 +9450,16 @@ ts-jest@^27.0.5: semver "7.x" yargs-parser "20.x" +ts-loader@^9.2.6: + version "9.2.6" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" + integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + tsconfig-paths@^3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" @@ -9472,11 +9563,16 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^4.0, typescript@^4.0.3: +typescript@^4.0: version "4.4.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324" integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== +typescript@^4.4.4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" + integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== + uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"