diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..cefbd69 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,12 @@ +{ + "root": true, + "env": { + "es2022": true + }, + "plugins": ["@typescript-eslint"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + } +} diff --git a/__tests__/.eslintrc.json b/__tests__/.eslintrc.json new file mode 100644 index 0000000..12eafbb --- /dev/null +++ b/__tests__/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "env": { + "jest": true + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"] +} diff --git a/package.json b/package.json index d1546bd..f4c9e38 100644 --- a/package.json +++ b/package.json @@ -62,8 +62,8 @@ "@types/jest": "^26.0.23", "@types/node": "^11.10.4", "@types/puppeteer": "^5.4.3", - "@typescript-eslint/eslint-plugin": "^5.23.0", - "@typescript-eslint/parser": "^5.23.0", + "@typescript-eslint/eslint-plugin": "^5.33.1", + "@typescript-eslint/parser": "^5.33.1", "babel-loader": "^8.2.5", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", "copy-webpack-plugin": "^5.0.0", @@ -102,42 +102,6 @@ "trailingComma": "all", "arrowParens": "avoid" }, - "eslintConfig": { - "root": true, - "env": { - "browser": true - }, - "parser": "@typescript-eslint/parser", - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended", - "plugin:react-hooks/recommended", - "prettier" - ], - "settings": { - "react": { - "version": "detect" - } - }, - "ignorePatterns": [ - "webpack.config.js", - "*jest*", - "scripts", - "dist", - "*-profile", - "Safari", - "vscode-icons", - "__tests__" - ], - "rules": { - "@typescript-eslint/ban-types": "off", - "react-hooks/rules-of-hooks": "off" - } - }, "lint-staged": { "*.scss": [ "yarn prettier --list-different --write" diff --git a/server/.eslintrc.json b/server/.eslintrc.json new file mode 100644 index 0000000..d92924e --- /dev/null +++ b/server/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "env": { + "node": true + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"] +} diff --git a/src/.eslintrc.json b/src/.eslintrc.json new file mode 100644 index 0000000..7674a32 --- /dev/null +++ b/src/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "env": { + "browser": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended", + "prettier" + ], + "settings": { + "react": { + "version": "detect" + } + }, + "rules": { + "react-hooks/rules-of-hooks": "off" // for IIFC + } +} diff --git a/src/common.d.ts b/src/common.d.ts index eee4e97..191c596 100644 --- a/src/common.d.ts +++ b/src/common.d.ts @@ -5,3 +5,5 @@ type ReactIO = { value: T onChange: Dispatch> } + +type PropsWithChildren = React.PropsWithChildren> diff --git a/src/containers/ConfigsContext.tsx b/src/containers/ConfigsContext.tsx index 53cb7cc..8d3a48b 100644 --- a/src/containers/ConfigsContext.tsx +++ b/src/containers/ConfigsContext.tsx @@ -1,14 +1,13 @@ +import { PropsWithChildren } from 'common' import * as React from 'react' import { Config, configHelper } from 'utils/config/helper' -type Props = {} - type ContextShape = IO> export type ConfigsContextShape = ContextShape export const ConfigsContext = React.createContext(null) -export function ConfigsContextWrapper(props: React.PropsWithChildren) { +export function ConfigsContextWrapper(props: PropsWithChildren) { const [configs, setConfigs] = React.useState(null) React.useEffect(() => { configHelper.get().then(setConfigs) diff --git a/src/containers/ErrorBoundary.tsx b/src/containers/ErrorBoundary.tsx index 1f9ba7c..8e3c202 100644 --- a/src/containers/ErrorBoundary.tsx +++ b/src/containers/ErrorBoundary.tsx @@ -1,7 +1,8 @@ import { raiseError } from 'analytics' +import { PropsWithChildren } from 'common' import * as React from 'react' -export class ErrorBoundary extends React.PureComponent> { +export class ErrorBoundary extends React.PureComponent { componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { raiseError(error, errorInfo) } diff --git a/src/containers/ErrorContext.tsx b/src/containers/ErrorContext.tsx index 01c3c7a..557e1a0 100644 --- a/src/containers/ErrorContext.tsx +++ b/src/containers/ErrorContext.tsx @@ -1,3 +1,4 @@ +import { PropsWithChildren } from 'common' import { useInspector } from 'containers/StateInspector' import * as React from 'react' import { useStateIO } from 'utils/hooks/useStateIO' @@ -6,7 +7,7 @@ export type SideBarErrorContextShape = IO export const SideBarErrorContext = React.createContext(null) -export function StateBarErrorContextWrapper({ children }: React.PropsWithChildren<{}>) { +export function StateBarErrorContextWrapper({ children }: PropsWithChildren) { const $error = useStateIO(null) useInspector('SideBarErrorContext', $error.value) diff --git a/src/containers/OAuthWrapper.tsx b/src/containers/OAuthWrapper.tsx index 808950d..ff06836 100644 --- a/src/containers/OAuthWrapper.tsx +++ b/src/containers/OAuthWrapper.tsx @@ -1,3 +1,4 @@ +import { PropsWithChildren } from 'common' import { useConfigs } from 'containers/ConfigsContext' import { platform } from 'platforms' import * as React from 'react' @@ -10,7 +11,7 @@ import { SideBarStateContext } from './SideBarState' /** * Setup access token before sending other requests */ -export function OAuthWrapper({ children }: React.PropsWithChildren<{}>) { +export function OAuthWrapper({ children }: PropsWithChildren) { const running = useGetAccessToken() const $state = useLoadedContext(SideBarStateContext) diff --git a/src/containers/ReloadContext.tsx b/src/containers/ReloadContext.tsx index 4e30436..b536ebe 100644 --- a/src/containers/ReloadContext.tsx +++ b/src/containers/ReloadContext.tsx @@ -1,3 +1,4 @@ +import { PropsWithChildren } from 'common' import * as React from 'react' import { noop } from 'utils/general' @@ -5,7 +6,7 @@ export type ReloadContextShape = () => void export const ReloadContext = React.createContext(noop) -export function ReloadContextWrapper({ children }: React.PropsWithChildren<{}>) { +export function ReloadContextWrapper({ children }: PropsWithChildren) { const [key, setKey] = React.useState(0) const reload = React.useCallback(() => setKey(key => key + 1), []) diff --git a/src/containers/RepoContext.tsx b/src/containers/RepoContext.tsx index b2ed22e..9298fb7 100644 --- a/src/containers/RepoContext.tsx +++ b/src/containers/RepoContext.tsx @@ -1,3 +1,4 @@ +import { PropsWithChildren } from 'common' import { useConfigs } from 'containers/ConfigsContext' import { platform } from 'platforms' import * as React from 'react' @@ -11,7 +12,7 @@ import { useInspector } from './StateInspector' export const RepoContext = React.createContext(null) -export function RepoContextWrapper({ children }: React.PropsWithChildren<{}>) { +export function RepoContextWrapper({ children }: PropsWithChildren) { const partialMetaData = usePartialMetaData() const defaultBranch = useDefaultBranch(partialMetaData) const metaData = useMetaData(partialMetaData, defaultBranch) diff --git a/src/containers/SideBarState.tsx b/src/containers/SideBarState.tsx index 8b1ba9d..d70816e 100644 --- a/src/containers/SideBarState.tsx +++ b/src/containers/SideBarState.tsx @@ -1,3 +1,4 @@ +import { PropsWithChildren } from 'common' import * as React from 'react' import { useStateIO } from 'utils/hooks/useStateIO' import { useInspector } from './StateInspector' @@ -18,7 +19,7 @@ export type SideBarStateContextShape = IO export const SideBarStateContext = React.createContext(null) -export function StateBarStateContextWrapper({ children }: React.PropsWithChildren<{}>) { +export function StateBarStateContextWrapper({ children }: PropsWithChildren) { const $state = useStateIO('disabled') useInspector('SideBarStateContext', $state.value) diff --git a/src/containers/StateInspector.tsx b/src/containers/StateInspector.tsx index efed98c..876c4ff 100644 --- a/src/containers/StateInspector.tsx +++ b/src/containers/StateInspector.tsx @@ -1,4 +1,4 @@ -import { ReactIO } from 'common' +import { PropsWithChildren, ReactIO } from 'common' import { IN_PRODUCTION_MODE } from 'env' import * as React from 'react' import { useStateIO } from 'utils/hooks/useStateIO' @@ -9,7 +9,7 @@ export const InspectorContext = React.createContext) { + : function InspectorContextWrapper({ children }: PropsWithChildren) { const $ = useStateIO({}) const [show, setShow] = React.useState(true) diff --git a/src/containers/Theme.tsx b/src/containers/Theme.tsx index b9f44b9..b68df0e 100644 --- a/src/containers/Theme.tsx +++ b/src/containers/Theme.tsx @@ -1,6 +1,7 @@ import primitives from '@primer/primitives' import { BaseStyles, ThemeProvider } from '@primer/react' import theme from '@primer/react/lib-esm/theme' +import { PropsWithChildren } from 'common' import * as React from 'react' // Temporary color fix for out-of-date embedded @primer/primitives in @primer/react @@ -48,7 +49,7 @@ function useThemePreference() { return prefer } -export function Theme({ children }: React.PropsWithChildren<{}>) { +export function Theme({ children }: PropsWithChildren) { const themePreference = useThemePreference() return ( diff --git a/src/global.d.ts b/src/global.d.ts index add2cd6..1182762 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -47,6 +47,8 @@ type MakeOptional = Override< type VoidFN = (payload: T) => void type Async = T | Promise + +// eslint-disable-next-line @typescript-eslint/ban-types type EnumString = S | (string & {}) type JSONPrimitive = string | number | boolean | null | undefined diff --git a/src/platforms/Gitea/API.ts b/src/platforms/Gitea/API.ts index 8494a27..88b73e7 100644 --- a/src/platforms/Gitea/API.ts +++ b/src/platforms/Gitea/API.ts @@ -19,9 +19,9 @@ async function request( accessToken?: string } = {}, ) { - const headers = {} as HeadersInit & { + const headers: HeadersInit & { Authorization?: string - } + } = {} if (accessToken) { headers.Authorization = `token ${accessToken}` } diff --git a/src/react-override.d.ts b/src/react-override.d.ts index 2a95754..9e91821 100644 --- a/src/react-override.d.ts +++ b/src/react-override.d.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ // Patch the removed `children` prop declare namespace React { - interface FunctionComponent

{ + interface FunctionComponent

{ (props: PropsWithChildren

, context?: any): ReactElement | null propTypes?: WeakValidationMap

| undefined contextTypes?: ValidationMap | undefined diff --git a/yarn.lock b/yarn.lock index cb28fd8..224679a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2654,85 +2654,85 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.23.0.tgz#bc4cbcf91fbbcc2e47e534774781b82ae25cc3d8" - integrity sha512-hEcSmG4XodSLiAp1uxv/OQSGsDY6QN3TcRU32gANp+19wGE1QQZLRS8/GV58VRUoXhnkuJ3ZxNQ3T6Z6zM59DA== +"@typescript-eslint/eslint-plugin@^5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz#c0a480d05211660221eda963cc844732fe9b1714" + integrity sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ== dependencies: - "@typescript-eslint/scope-manager" "5.23.0" - "@typescript-eslint/type-utils" "5.23.0" - "@typescript-eslint/utils" "5.23.0" - debug "^4.3.2" + "@typescript-eslint/scope-manager" "5.33.1" + "@typescript-eslint/type-utils" "5.33.1" + "@typescript-eslint/utils" "5.33.1" + debug "^4.3.4" functional-red-black-tree "^1.0.1" - ignore "^5.1.8" + ignore "^5.2.0" regexpp "^3.2.0" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.23.0.tgz#443778e1afc9a8ff180f91b5e260ac3bec5e2de1" - integrity sha512-V06cYUkqcGqpFjb8ttVgzNF53tgbB/KoQT/iB++DOIExKmzI9vBJKjZKt/6FuV9c+zrDsvJKbJ2DOCYwX91cbw== +"@typescript-eslint/parser@^5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.33.1.tgz#e4b253105b4d2a4362cfaa4e184e2d226c440ff3" + integrity sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA== dependencies: - "@typescript-eslint/scope-manager" "5.23.0" - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/typescript-estree" "5.23.0" - debug "^4.3.2" + "@typescript-eslint/scope-manager" "5.33.1" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/typescript-estree" "5.33.1" + debug "^4.3.4" -"@typescript-eslint/scope-manager@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.23.0.tgz#4305e61c2c8e3cfa3787d30f54e79430cc17ce1b" - integrity sha512-EhjaFELQHCRb5wTwlGsNMvzK9b8Oco4aYNleeDlNuL6qXWDF47ch4EhVNPh8Rdhf9tmqbN4sWDk/8g+Z/J8JVw== +"@typescript-eslint/scope-manager@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz#8d31553e1b874210018ca069b3d192c6d23bc493" + integrity sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA== dependencies: - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/visitor-keys" "5.23.0" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/visitor-keys" "5.33.1" -"@typescript-eslint/type-utils@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.23.0.tgz#f852252f2fc27620d5bb279d8fed2a13d2e3685e" - integrity sha512-iuI05JsJl/SUnOTXA9f4oI+/4qS/Zcgk+s2ir+lRmXI+80D8GaGwoUqs4p+X+4AxDolPpEpVUdlEH4ADxFy4gw== +"@typescript-eslint/type-utils@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz#1a14e94650a0ae39f6e3b77478baff002cec4367" + integrity sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g== dependencies: - "@typescript-eslint/utils" "5.23.0" - debug "^4.3.2" + "@typescript-eslint/utils" "5.33.1" + debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.23.0.tgz#8733de0f58ae0ed318dbdd8f09868cdbf9f9ad09" - integrity sha512-NfBsV/h4dir/8mJwdZz7JFibaKC3E/QdeMEDJhiAE3/eMkoniZ7MjbEMCGXw6MZnZDMN3G9S0mH/6WUIj91dmw== +"@typescript-eslint/types@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.33.1.tgz#3faef41793d527a519e19ab2747c12d6f3741ff7" + integrity sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ== -"@typescript-eslint/typescript-estree@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.23.0.tgz#dca5f10a0a85226db0796e8ad86addc9aee52065" - integrity sha512-xE9e0lrHhI647SlGMl+m+3E3CKPF1wzvvOEWnuE3CCjjT7UiRnDGJxmAcVKJIlFgK6DY9RB98eLr1OPigPEOGg== +"@typescript-eslint/typescript-estree@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz#a573bd360790afdcba80844e962d8b2031984f34" + integrity sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA== dependencies: - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/visitor-keys" "5.23.0" - debug "^4.3.2" - globby "^11.0.4" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/visitor-keys" "5.33.1" + debug "^4.3.4" + globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.23.0.tgz#4691c3d1b414da2c53d8943310df36ab1c50648a" - integrity sha512-dbgaKN21drqpkbbedGMNPCtRPZo1IOUr5EI9Jrrh99r5UW5Q0dz46RKXeSBoPV+56R6dFKpbrdhgUNSJsDDRZA== +"@typescript-eslint/utils@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.33.1.tgz#171725f924fe1fe82bb776522bb85bc034e88575" + integrity sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.23.0" - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/typescript-estree" "5.23.0" + "@typescript-eslint/scope-manager" "5.33.1" + "@typescript-eslint/types" "5.33.1" + "@typescript-eslint/typescript-estree" "5.33.1" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.23.0.tgz#057c60a7ca64667a39f991473059377a8067c87b" - integrity sha512-Vd4mFNchU62sJB8pX19ZSPog05B0Y0CE2UxAZPT5k4iqhRYjPnqyY3woMxCd0++t9OTqkgjST+1ydLBi7e2Fvg== +"@typescript-eslint/visitor-keys@5.33.1": + version "5.33.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz#0155c7571c8cd08956580b880aea327d5c34a18b" + integrity sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg== dependencies: - "@typescript-eslint/types" "5.23.0" - eslint-visitor-keys "^3.0.0" + "@typescript-eslint/types" "5.33.1" + eslint-visitor-keys "^3.3.0" "@webassemblyjs/ast@1.8.5": version "1.8.5" @@ -5412,7 +5412,7 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@3.3.0, eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@3.3.0, eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== @@ -6507,7 +6507,7 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== -globby@^11.0.4: +globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -6917,7 +6917,7 @@ ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==